《东华大学2020年程序设计竞赛题解》
D:
思路:模拟.
因为n的数量比较小。所以可以去模拟这个操作.
每次给最小的加上n-1,其他的减去1.当a[1] < 0时说明不合法.
当a[1] = a[n]时说明可以实现。
因为a[n]的值在[0,1000],所以很明显这个模拟次数最多1000次.
当1000次还没退出时说明在这之前肯定出现过重复状态.那么说明是无法实现的.
Code:
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> pii; const int N = 1e5+5; const int M = 1e6+5; const int Mod = 1e9+7; #define pi acos(-1) #define INF 1e8 #define INM INT_MIN #define pb(a) push_back(a) #define mk(a,b) make_pair(a,b) #define dbg(x) cout << "now this num is " << x << endl; #define met0(axx) memset(axx,0,sizeof(axx)); #define metf(axx) memset(axx,-1,sizeof(axx)); #define sd(ax) scanf("%d",&ax) #define sld(ax) scanf("%lld",&ax) #define sldd(ax,bx) scanf("%lld %lld",&ax,&bx) #define sdd(ax,bx) scanf("%d %d",&ax,&bx) #define sddd(ax,bx,cx) scanf("%d %d %d",&ax,&bx,&cx) #define sfd(ax) scanf("%lf",&ax) #define sfdd(ax,bx) scanf("%lf %lf",&ax,&bx) #define pr(a) printf("%d\n",a) #define plr(a) printf("%lld\n",a) int a[105]; void slove() { int t;sd(t); while(t--) { int n,sum = 0;sd(n); for(int i=1;i<=n;++i) sd(a[i]),sum += a[i]; if(sum%n != 0) printf("No\n"); else { sort(a+1,a+n+1); bool f = false; for(int i=1;i<=1000;++i) { if(a[1] == a[n]) {f = true;break;} if(a[1] < 0) break; a[1] += n-1;for(int j=2;j<=n;++j) a[j]--; sort(a+1,a+n+1); } printf("%s\n",f ? "Yes" : "No"); } } } int main() { slove(); // system("pause"); return 0; }
F:博弈论
思路:
可以发现对于0的操作,可以看成无效。
因为先手将00变成1,后手可以直接将他变成0.这样操作相当于无效。
所以只有原来的1的个数会影响结果。
那么显然当原来串中1的个数为奇数个时,先手必赢,反之后手必赢.
Code:
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> pii; const int N = 1e5+5; const int M = 1e6+5; const int Mod = 1e9+7; #define pi acos(-1) #define INF 1e8 #define INM INT_MIN #define pb(a) push_back(a) #define mk(a,b) make_pair(a,b) #define dbg(x) cout << "now this num is " << x << endl; #define met0(axx) memset(axx,0,sizeof(axx)); #define metf(axx) memset(axx,-1,sizeof(axx)); #define sd(ax) scanf("%d",&ax) #define sld(ax) scanf("%lld",&ax) #define sldd(ax,bx) scanf("%lld %lld",&ax,&bx) #define sdd(ax,bx) scanf("%d %d",&ax,&bx) #define sddd(ax,bx,cx) scanf("%d %d %d",&ax,&bx,&cx) #define sfd(ax) scanf("%lf",&ax) #define sfdd(ax,bx) scanf("%lf %lf",&ax,&bx) #define pr(a) printf("%d\n",a) #define plr(a) printf("%lld\n",a) int check(string s) { int sum = 0; for(int i=0;i<s.size();++i) { if(s[i] == '1') sum++; } if(sum&1) return 1; return 0; } void slove() { int t;sd(t); while(t--) { int n,cnt = 0;sd(n); while(n--) { string s;cin >> s; if(check(s)) cnt++; } if(cnt != 0) printf("sdzNB\n"); else printf("kgNB\n"); } } int main() { slove(); // system("pause"); return 0; }
G:
显然对于1,我们去加它更好优.
我们考虑结果为若干个乘积相加的形式.
两个数连乘
-1 -1 -1*-1 = 1比加优
三个数连乘
-1 1 -1 -1*-1*1 = 1比加优
四个数连乘
-1 1 1 -1 -1*1*-1*1 = 1比加优.
五个数连乘
-1 1 1 1 -1 加和乘一样.
6..7...8都不再有乘比加优的情况.
说明最多出现四个数连乘的状态.
那么定义dp[i][2].
dp[i][0] - 表示和前面一个数相乘,到i位置的最大价值.
dp[i][1] - 表示和前面一个数相加,到i位置的最大价值.
转移:
对于相加很简单
dp[i][1] = max(dp[i-1][1]+a[i],dp[i-1][0]+a[i]);
对于相乘枚举两个数相乘.三个数相乘.四个数相乘。更新dp[i][0].
Code:
View Code
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> pii; const int N = 1e5+5; const int M = 1e6+5; const int Mod = 1e9+7; #define pi acos(-1) #define INF 1e8 #define INM INT_MIN #define pb(a) push_back(a) #define mk(a,b) make_pair(a,b) #define dbg(x) cout << "now this num is " << x << endl; #define met0(axx) memset(axx,0,sizeof(axx)); #define metf(axx) memset(axx,-1,sizeof(axx)); #define sd(ax) scanf("%d",&ax) #define sld(ax) scanf("%lld",&ax) #define sldd(ax,bx) scanf("%lld %lld",&ax,&bx) #define sdd(ax,bx) scanf("%d %d",&ax,&bx) #define sddd(ax,bx,cx) scanf("%d %d %d",&ax,&bx,&cx) #define sfd(ax) scanf("%lf",&ax) #define sfdd(ax,bx) scanf("%lf %lf",&ax,&bx) #define pr(a) printf("%d\n",a) #define plr(a) printf("%lld\n",a) /* 考虑结果为若干个乘积相加的形式. 两个数连乘 -1 -1 -1*-1 = 1比加优 三个数连乘 -1 1 -1 -1*-1*1 = 1比加优 四个数连乘 -1 1 1 -1 -1*1*-1*1 = 1比加优. 五个数连乘 -1 1 1 1 -1 加和乘一样. */ int a[N]; int dp[N][2];//和前面的乘,和前面的加. void slove() { int t;sd(t); while(t--) { met0(dp); int n;sd(n); for(int i=1;i<=n;++i) sd(a[i]); dp[1][0] = dp[1][1] = a[1]; for(int i=2;i<=n;++i) { dp[i][0] = max(dp[i][0],max(dp[i-2][1]+a[i-1]*a[i],dp[i-2][0]+a[i-1]*a[i]));//两个连乘 if(i >= 3) dp[i][0] = max(dp[i][0],max(dp[i-3][1]+a[i-2]*a[i-1]*a[i],dp[i-3][0]+a[i-2]*a[i-1]*a[i]));//三个连乘 if(i >= 4)//四个连乘 { int t1 = dp[i-4][0]+a[i-3]*a[i-2]*a[i-1]*a[i]; int t2 = dp[i-4][1]+a[i-3]*a[i-2]*a[i-1]*a[i]; dp[i][0] = max(dp[i][0],max(t1,t2)); } dp[i][1] = max(dp[i][1],dp[i-1][1]+a[i]); dp[i][1] = max(dp[i][1],dp[i-1][0]+a[i]); } pr(max(dp[n][1],dp[n][0])); } } int main() { slove(); system("pause"); return 0; } /* -1 1 -1 -1*1*-1 = 1 -1 1 1 -1 -1*1*1*-1 = 1 -1 1 1 1 -1 */