• CF666Div2题解与总结


    先放个链接:https://codeforc.es/contest/1397

    中规中矩的一场比赛吧,但没有AK...考场最后一题没过,赛后想想主要原因还是D题意看错,(英文不好),导致打得很慢(同样A4题,有人rk30,我rk400)

    写个简单题解吧,重点讲一下C和E

    A题:送分题,没什么好说的,判一下字母数是否平均分成n份就做完了

    /*A. Juggling Letters*/ 
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    char str[1010];
    int cnt[27];
    int main()
    {
    	int t;
    	cin >> t;
    	while(t--){
    		memset(cnt,0,sizeof(cnt));
    		int n;
    		scanf("%d",&n);
    		for(int i = 1; i <= n; ++i){
    			scanf("%s",str+1);
    			int len = strlen(str+1);
    			for(int j = 1; j <= len; ++j)
    				cnt[str[j] - 'a']++;
    		}
    		bool flag = true;
    		for(int i = 0; i <= 'z' - 'a'; ++i){
    			if(cnt[i] % n)		flag = false;
    		}
    		if(flag)	puts("YES");
    		else	puts("NO");
    	}
    	return 0;
    }
    

      B题依然送分,题面看着很可怕,但其实我们可以意识到c^n次方非常大(即有很多情况是可以提前判掉的),所以可以暴枚这个数组,然后有个显然的贪心就是给定两个数组a,b,要最小化∑|a-bi|,就要把a,b排序后按位减

    /*B. Power Sequence*/
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define ll long long
    const int maxn = 1e5 + 10;
    ll a[maxn],p[maxn];
    int read(){
    	char c = getchar();
    	int x = 0;
    	while(c < '0' || c > '9')		c = getchar();
    	while(c >= '0' && c <= '9')		x = x * 10 + c - 48,c = getchar();
    	return x;
    }
    const ll inf = 1e15;
    int main()
    {
    	int n = read();
    	ll ans = 2e18;
    	for(int i = 0; i < n; ++i)
    		a[i] = read();
    	sort(a,a+n) ;
    	ll x = 1;
    	while(1){
    		bool flag = false;
    		p[0] = 1;
    		for(int i = 1; i < n; ++i){
    			p[i] = p[i-1] * x;
    			if(p[i] >= inf){
    				flag = true;
    				break;
    			}
    		}
    		if(flag)	break;
    		x++;
    		ll res = 0;
    		for(int i = 0; i < n; ++i)
    			res += abs(p[i] - a[i]);
    		ans = min(ans,res);
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    

      C题比较有意思,为什么构造是3次?我们可以先把an搞成0(这个是显然可以的,因为任何数都是1的倍数),然后分别对1~n-1,1~n搞,问题就转化为求a * (n-1)  - b * n = -a[i] 

    因为对于任意n,都有gcd(n,n-1) = 1,所以根据Bezout定理,这个不定方程一定有整数解,拓欧求一下即可

    /*C. Multiples of Length*/
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    const int maxn = 1e5 + 10;
    int a[maxn];
    ll b[maxn];
    int read(){
    	int f = 1;
    	int x = 0;
    	char c = getchar();
    	while(c < '0' || c > '9')		f = (c == '-')?-1:f,c = getchar();
    	while(c >= '0' && c <= '9')		x = x * 10 + c - 48,c = getchar();
    	return x * f;
    }
    ll exgcd(ll a,ll b,ll &x,ll &y){
    	if(b == 0){
    		x = 1,y = 0;
    		return a;
    	}
    	ll d = exgcd(b,a%b,x,y);
    	ll z = x;x = y;y = z - (a / b) * y;
    	return d;
    }
    int main()
    {
    	int n = read();
    	for(int i = 1; i <= n; ++i)
    		a[i] = read();
    	if(n == 1){
    		printf("1 1
    ");
    		printf("%d
    ",-1*a[1]);
    		printf("1 1
    0
    ");
    		printf("1 1
    0
    ");
    		return 0;
    	}
    	if(n == 2){
    		printf("1 1
    %d
    ",-1*a[1]);
    		printf("2 2
    %d
    ",-1*a[2]);
    		printf("1 1
    0
    ");
    		return 0;
    	}
    	if(n == 3){
    		printf("1 1
    %d
    ",-1*a[1]);
    		printf("2 2
    %d
    ",-1*a[2]);
    		printf("3 3
    %d
    ",-1*a[3]);
    		return 0;
    	}
    	ll x = 0,y = 0;
    	exgcd(n,n-1,x,y);
    	printf("1 1
    %d
    ",-1*a[1]);
    	printf("%d %d
    ",2,n);
    	for(int i = 2; i <= n; ++i){
    		printf("%lld ",1ll * x * (n - 1) * a[i]);
    	}
    	puts("");
    	printf("%d %d
    ",1,n);
    	for(int i = 1; i <= n; ++i){
    		if(i == 1)		printf("%d ",0);
    		else	printf("%lld ",1ll * y * n * a[i]);
    	}
    	return 0;
    }
    

      D题不说了,简单贪心,每次取能取的最大,就过了

    /*Stoned Games*/
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    #define ll long long
    int a[110];
    struct Num{
    	int id,v;
    };
    bool operator < (Num A,Num B) {
    	return A.v < B.v;
    }
    priority_queue<Num>q;
    int read(){
    	char c = getchar();
    	int x = 0;
    	while(c < '0' || c > '9')		c = getchar();
    	while(c >= '0' && c <= '9')		x = x * 10 + c - 48,c = getchar();
    	return x;
    }
    int main()
    {
    	int t = read();
    	while(t--){
    		int n = read();
    		while(!q.empty())	q.pop();
    		for(int i = 1; i <= n; ++i)
    			a[i] = read(),q.push(Num{i,a[i]});
    		int cnt = 0;
    		int lst = 0;
    		while(1){
    			if(q.empty())	break;
    			Num now = q.top();Num A;
    			if(now.id == lst){
    				//if(q.empty())	break;
    				q.pop();
    				if(q.empty())	break;
    				A = q.top();
    				q.pop();
    				lst = A.id;
    				if(A.v >= 2)
    					q.push(Num{A.id,A.v-1});
    				q.push(now);
    			}
    			else{
    				lst = now.id;
    				q.pop();
    				if(now.v >= 2)
    					q.push(Num{now.id,now.v-1});
    			}
    			cnt++;
    		}
    		if(cnt & 1)		puts("T");
    		else	puts("HL");
    	}
    	return 0;
    }
    

      E题比较有意思,对于这种有一堆操作的,一般都只有几种操作有用,其实可以发现,对于一组怪,要么直接全部杀死,要么就只有boss剩1滴血,又因为每组怪都要处理,所以最优解钟最多只有前一个的怪还没有打完(即boss剩一滴血的情况),所以可以根据这个性质DP,具体看代码,有注释

    /*E Monster Invader*/
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    const int maxn = 1e6 + 10;
    ll f[maxn][2];/*f[i][0] (1~i has finished) f[i][1] (only the boss of i hasn't finished)*/
    ll A[maxn],B[maxn],C[maxn];
    ll read(){
    	char c = getchar();
    	ll x = 0;
    	while(c < '0' || c > '9')	 	c = getchar();
    	while(c >= '0' && c <= '9')		x = x * 10 + c - 48,c = getchar();
    	return x;
    }
    int a[maxn];
    int main()
    {
    	int n = read();
    	ll r1 = read(),r2 = read(),r3 = read(),d = read();
    	for(int i = 1; i <= n; ++i)		a[i] = read();
    	memset(f,0x3f,sizeof(f));
    	f[0][0] = 0;
    	for(int i = 1; i <= n; ++i){
    		A[i] = min(min(r2,r1),r3);/*一击必杀最小代价*/
    		B[i] = min(r3,r1) * a[i] + r3;/*直接清理掉的最小代价*/
    		C[i] = min((min(r3,r1) * a[i] + r1),r2);/*剩boss一滴血的最小代价*/
    	}
    	for(int i = 1; i <= n; ++i) {
    		if(i == 1)
    			f[i][0] = B[i],f[i][1] = f[i-1][0] + C[i];
    		else{
    			int k = (i == n)?2:3;
    			f[i][0] = min(min(f[i-1][0] + B[i] + d,f[i-1][0] + C[i] + 3 * d + A[i]),min(f[i-1][1] + k * d + B[i] + A[i-1],
    			f[i-1][1] + 3 * d + C[i] + A[i-1] + A[i]));
    			f[i][1] = f[i-1][0] + C[i] + d;
    		}
    		//printf("f[%d][0] = %lld f[%d][1] = %lld
    ",i,f[i][0],i,f[i][1]);
    	}
    	printf("%lld
    ",f[n][0]);
    	return 0;
    }
    

      

  • 相关阅读:
    284. Peeking Iterator 光是看看下一个值的遍历
    339. Nested List Weight Sum 339.嵌套列表权重总和
    341. Flatten Nested List Iterator展开多层数组
    springcloud之配置中心服务化和高可用
    springcloud之配置中心git
    springcloud之熔断监控Hystrix Dashboard和Turbine
    springcloud之熔断器Hystrix
    springcloud之服务提供与调用
    springcloud之注册中心Eureka
    springcloud之大话springcloud
  • 原文地址:https://www.cnblogs.com/y-dove/p/13598581.html
Copyright © 2020-2023  润新知