Playing with Numbers(Kattis - playingwithnumbers)(預處理瞎搞)

題目鏈接:https://vjudge.net/problem/Kattis-playingwithnumbers

題目描述:給定n組a b的值,每組表示一個數值2^a*3^b,共進行n次操作,第i次操作可以進行i-1次gcd操作和 n - i次lcm操作,求每次操作後所得最大值及最小值對應的ab分別是多少。每次選取任意兩個數進行gcd操作時,只將結果放回這些數字中,lcm也是。

思路:當至少進行2次gcd操作時,一定能將兩個最小的ab值mina minb組合到一起,所得最小值一定是2^mina*3minb;至少進行2次lcm操作時,一定能將兩個最大的ab值mina minb組合到一起,所得最大值一定是2^maxa*3maxb。當只進行gcd或lcm時,所得結果是唯一的,輸出即可。當只進行1次gcd時,也就是要選取一個數與其他n-1個數的lcm進行gcd操作,可以預處理好數組lcm1[i]代表除第i個數的a值以外,其他n-1個數的a值進行lcm結果,遍歷一遍取最小值,b值求法相同;當只進行1次lcm時,也就是要選取一個數與其他n-1個數的gcd進行lcm操作得到最大值,可以預處理好數組lcm1[i]代表除第i個數以外的a值,其他n-1個數的a值進行lcm結果,遍歷一遍取最大值,b值求法相同。代碼寫的有點麻煩,但是思路還是很簡單的,只要別寫暈了就行。吐槽一下只有25組測試數據真的很水,場上我的思路不對隊友都可以舉出反例來竟然照樣能AC,沒辦法最後五分鐘算是交着玩了我也不知道會AC啊,隊友對此表示難以接受哈哈。寫這道題做的最多的就是複製粘貼,醉了。

代碼如下:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn=50000+10;
int n;
int a[maxn],b[maxn];
const int inf=0x3f3f3f3f;
struct node{
    int a, b;
    int id;
    node(int a = 0, int b = 0, int id = 0) : a(a), b(b), id(id) {}
}num[maxn];
int gcd1[maxn], lcm1[maxn], gcd2[maxn], lcm2[maxn];
int max1[maxn], max2[maxn], min1[maxn], min2[maxn];
int mmax1[maxn], mmax2[maxn], mmin1[maxn], mmin2[maxn];
int main(){
    while(~scanf("%d",&n)){
        int maxa=0,maxb=0,mina=inf,minb=inf;
        int dyb,dya,ddyb,ddya;
        for(int i=1; i<=n; i++){
            scanf("%d%d",&num[i].a,&num[i].b);
            if(num[i].a > maxa) maxa = num[i].a;//分別找出最大最小的ab值
            if(num[i].b > maxb) maxb = num[i].b;
            if(num[i].a < mina) mina = num[i].a;
            if(num[i].b < minb) minb = num[i].b;
        }
        if(n==1){
            printf("%d %d %d %d\n",num[1].a,num[1].b,num[1].a,num[1].b); continue;
        }
        if(n==2){
            printf("%d %d %d %d\n",maxa,maxb,maxa,maxb);
            printf("%d %d %d %d\n",mina,minb,mina,minb);
            continue;
        }
        min1[2] = num[1].a; min2[2] = num[1].b;
        max1[2] = num[1].a; max2[2] = num[1].b;
        for(int i = 3; i <= n; ++i){
            min1[i] = min(num[i - 1].a, min1[i - 1]);//min1[i]表示前i-1個數a中的最小值,也就是i前面所有a的gcd結果
            min2[i] = min(num[i - 1].b, min2[i - 1]);//i前面所有b的gcd結果
            max1[i] = max(num[i - 1].a, max1[i - 1]);//i前面所有a的lcm結果
            max2[i] = max(num[i - 1].b, max2[i - 1]);//i前面所有b的lcm結果
        }
        mmin1[n - 1] = num[n].a; mmin2[n - 1] = num[n].b;
        mmax1[n - 1] = num[n].a; mmax2[n - 1] = num[n].b;
        for(int i = n - 2; i >= 1; --i){
            mmin1[i] = min(num[i + 1].a, mmin1[i + 1]);//i後面所有a的gcd結果
            mmin2[i] = min(num[i + 1].b, mmin2[i + 1]);//i後面所有b的gcd結果
            mmax1[i] = max(num[i + 1].a, mmax1[i + 1]);//i後面所有a的lcm結果
            mmax2[i] = max(num[i + 1].b, mmax2[i + 1]);//i後面所有b的lcm結果
        }
        gcd1[1] = mmin1[1]; lcm1[1] =  mmax1[1];
        gcd2[1] = mmin2[1]; lcm2[1] =  mmax2[1];
        gcd1[n] = min1[n]; lcm1[n] = max1[n];
        gcd2[n] = min2[n]; lcm2[n] = max2[n];
        for(int i = 2; i < n; ++i){
            gcd1[i] = min(min1[i], mmin1[i]);//除第i個數以外其他n-1個a的gcd結果
            gcd2[i] = min(min2[i], mmin2[i]);//除第i個數以外其他n-1個b的gcd結果
            lcm1[i] = max(max1[i], mmax1[i]);//除第i個數以外其他n-1個a的lcm結果
            lcm2[i] = max(max2[i], mmax2[i]);//除第i個數以外其他n-1個a的lcm結果
        }
        int cnt = 0;
        int u,v;
        int tmp1, tmp2, tmp3, tmp4, x, y;
        for(int i = 1; i <= n; ++i){
            tmp1 = tmp2 = 0;
            tmp3 = tmp4 = 1e9;
            u = i - 1;//gcd
            v = n - i;//lcm
            if(!u){//gcd次數爲0,lcm次數爲n-1,即求這n個數的最小公倍數,所得結果是唯一的2^maxa*3^maxb
                printf("%d %d %d %d\n", maxa, maxb, maxa, maxb); continue;
            }
            if(!v){//gcd次數爲n-1,lcm次數爲0,即求這n個數的最大公約數,所得結果也是唯一的2^mina*3^minb
                printf("%d %d %d %d\n", mina, minb, mina, minb); continue;
            }
            if(v == 1){//只進行一次lcm時,枚舉所有結果取最大值
                tmp1 = max(num[1].a, gcd1[1]); tmp2 = max(num[1].b, gcd2[1]);
                for(int i = 2; i <= n; ++i){
                    x = max(gcd1[i], num[i].a); y = max(gcd2[i], num[i].b);//第i個數與其他n-1的數的gcd結果進行lcm操作,也就是取較大者
                    if(x * log(2) + y * log(3) > tmp1 * log(2) + tmp2 * log(3)){
                        tmp1 = x; tmp2 = y;
                    }
                }
            }
            if(u == 1){//只進行一次gcd時,枚舉所有結果取最小值
                tmp3 = min(num[1].a, lcm1[1]); tmp4 = min(num[1].b, lcm2[1]);
                for(int i = 2; i <= n; ++i){
                    x = min(lcm1[i], num[i].a); y = min(lcm2[i], num[i].b);//第i個數與其他n-1的數的lcm結果進行gcd操作,也就是取較小者
                    if(x * log(2) + y * log(3) < tmp3 * log(2) + tmp4 * log(3)){
                        tmp3 = x; tmp4 = y;
                    }
                }
            }
            if(v >= 2){//進行兩次以上lcm,所得最大值一定是2^maxa*3^maxb
                tmp1 = maxa; tmp2 = maxb;
            }
            if(u >= 2){//進行兩次以上gcd,所得最小值一定是2^mina*3^minb
                tmp3 = mina; tmp4 = minb;
            }
            printf("%d %d %d %d\n", tmp1, tmp2, tmp3, tmp4);
        }
    }
    return 0;
}

/*

4
0 0
1 2
2 1
2 2

3
1 5
4 2
1 1

5
1 7
2 6
4 5
2 1
9 0

*/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章