• 【AtCoder】ARC094(C-F)题解


    C - Same Integers

    题解

    要么三个都达到最大的数,要么三个都到达最大的数+1,判断是前一种情况的方法是不断垫高前两大的,看之后最小的那个和最大的那个差值是不是2的倍数
    否则就是第二种情况

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <ctime>
    #include <vector>
    //#define ivorysi
    #define MAXN 100005
    #define eps 1e-7
    #define mo 974711
    #define pb push_back
    #define mp make_pair
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    const int P = 100000;
    int a[5];
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        for(int i = 1 ; i <= 3 ; ++i) scanf("%d",&a[i]);
        sort(a + 1,a + 4);
        if((a[3] - (a[1] + a[3] - a[2])) % 2 == 0) {
        	printf("%d
    ",a[3] - a[2] + (a[3] - (a[1] + a[3] - a[2])) / 2);
        }
        else {
        	++a[3];++a[1];
        	if(a[2] < a[1]) swap(a[2],a[1]);
        	int cnt = 1 + a[3] - a[2] + (a[3] - (a[1] + a[3] - a[2])) / 2;
        	printf("%d
    ",cnt);
        }
    }
    

    D - Worst Case

    题解

    先二分一个答案,然后两两数乘积分个段的话是个二次函数,可以三分求极值
    WA了无数次,我实在不知道段该怎么分,我把能分的部分都给取个max,然后过了

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <ctime>
    #include <vector>
    //#define ivorysi
    #define MAXN 100005
    #define eps 1e-7
    #define mo 974711
    #define pb push_back
    #define mp make_pair
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    int64 A,B;
    int Q;
    int64 calc(int64 X,int64 MID) {
        int64 s = MID,t = X - MID + 2;
        if(s >= A) ++s;
        if(t <= B) --t;
        return  s * t;
    }
    int64 get_Max(int64 X,int64 L,int64 R) {
        while(R - L + 1 >= 3) {
        	int64 K = (R - L + 1) / 3;
        	int64 LB = L + K,RB = R - K;
        	if(calc(X,LB) < calc(X,RB)) L = LB;
        	else R = RB;
        }
        int64 ans = 0;
        for(int64 i = L ; i <= R ; ++i) ans = max(ans,calc(X,i));
        return ans;
    }
    int64 check(int64 MID) {
        int64 res = 0;
        res = max(get_Max(MID,1,A - 1),res);
        res = max(get_Max(MID,MID - A + 2,MID),res);
        res = max(get_Max(MID,1,B - 1),res);
        res = max(get_Max(MID,MID - B + 2,MID),res);
        res = max(get_Max(MID,A,B),res);
        res = max(get_Max(MID,A,MID - B + 2),res);
        res = max(get_Max(MID,B,MID - A + 2),res);
        return res;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        scanf("%d",&Q);
        while(Q--) {
    	scanf("%lld%lld",&A,&B);
    	if(A > B) swap(A,B);
    	int64 P = A * B;
    	int64 L = 0,R = (A + B);
    	while(L < R) {
    	    int64 MID = (L + R + 1) >> 1;
    	    if(check(MID) < P) L = MID;
    	    else R = MID - 1;
    	}
    	printf("%lld
    ",L);
        }
    }
    

    E - Tozan and Gezan

    题解

    显然最后会Tozan最后不得不剩下一个A[i] > B[i]且B[i]最小的一块,这是最优的
    求个和减去这个B[i]就行

    如果都相等就是0

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <ctime>
    #include <vector>
    //#define ivorysi
    #define MAXN 200005
    #define eps 1e-7
    #define mo 974711
    #define pb push_back
    #define mp make_pair
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    int64 A[MAXN],B[MAXN],sum;
    int N;
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        scanf("%d",&N);
        for(int i = 1 ; i <= N ; ++i) scanf("%lld%lld",&A[i],&B[i]);
        int64 minn = 0x7fffffff;
        for(int i = 1 ; i <= N ; ++i) {
        	sum += B[i];
        	if(B[i] < A[i]) minn = min(B[i],minn);
        }
        if(minn == 0x7fffffff) puts("0");
        else printf("%lld
    ",sum - minn);
    }
    

    F - Normalization

    题解

    如果s中每个数都相等,那么答案是1

    如果s<=3暴搜

    之后我们发现如果a = 0,b = 1,c = 2
    那么变换后的串和原来的串总和是一样的
    而且变换后的串里面一定有两个相邻数字是一样的

    如何证明呢,我们把长度为4的情况暴搜一下,发现是对的,然后以后长度的情况就可以把第一个字符改成对的然后删掉第一个字符递归证明

    然后用一个dp求出这样的串,同时若没有两个相邻数字是一样的,还要检查一下S本身是不是一个这样的串

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <ctime>
    #include <vector>
    //#define ivorysi
    #define MAXN 200005
    #define eps 1e-7
    #define mo 974711
    #define pb push_back
    #define mp make_pair
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    const int64 MOD = 998244353;
    int N;
    char s[MAXN];
    int64 dp[MAXN][3][3][2];
    void inc(int64 &x,int64 y) {
        x = x + y;
        while(x >= MOD) x -= MOD;
    }
         
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        scanf("%s",s + 1);
        N = strlen(s + 1);
        bool all_same = 1;
        for(int i = 1 ; i <= N ; ++i) {
        	if(s[i] != s[1]) all_same = 0;
        }
        if(all_same) {puts("1");return 0;}
        if(N > 3) {
        	for(int i = 0 ; i <= 2 ; ++i) dp[1][i][i][0] = 1;
        	for(int i = 2 ; i <= N ; ++i) {
        	    for(int s = 0 ; s <= 2 ; ++s) {
        		for(int j = 0 ; j <= 2 ; ++j) {
        		    for(int h = 0 ; h <= 2 ; ++h) {
        			for(int l = 0 ; l <= 1 ; ++l) {
        			    inc(dp[i][(s + h) % 3][h][l || h == j],dp[i - 1][s][j][l]);
        			}
        		    }
        		}
        	    }
        	}
        	bool flag = 1;
        	int c = 0;
        	for(int i = 1 ; i <= N ; ++i) {
        	    c = (c + s[i] - 'a') % 3;
        	}
        	for(int i = 2 ; i <= N ; ++i) {
        	    if(s[i] == s[i - 1]) {flag = 0;break;}
        	}
        	int64 ans = flag;
        	for(int i = 0 ; i <= 2 ; ++i) ans += dp[N][c][i][1];
        	ans %= MOD;
        	printf("%lld
    ",ans);
        }
        else {
        	if(N == 3) {
        	    if(s[1] != s[2] && s[2] != s[3] && s[1] != s[3]) puts("3");
        	    else if(s[1] == s[2] || s[2] == s[3]) puts("6");
        	    else puts("7");
        	}
        	else if(N == 2) {
        	    puts("2");
        	}
        }
        return 0;
    }
    
  • 相关阅读:
    Java LinkedHashMap 逆序遍历
    (java/javascript) list 交集 并集 差集 去重复并集
    Map集合的四种遍历方式(转载)
    本地jar包 安装到本地仓库中的命令
    BigDecimal加减乘除运算(转)
    反射与内置方法
    项目二:选课系统
    绑定方法与非绑定方法
    多态性与鸭子类型
    继承与派生
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9052995.html
Copyright © 2020-2023  润新知