Educational Codeforces Round 84 (Rated for Div. 2) A-E题解
A. Sum of Odd Integers
首先可以算出从1开始到第k个奇数之和。如果和大于n,则不可能存在k个奇数加和等于n,否则用n减去前k个奇数的和,这个差值若是偶数,直接加到最大的奇数上,就可以满足题意要求,否则输出no。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int main(){ 5 int t; 6 cin>>t; 7 while(t--){ 8 ll n,k; 9 cin>>n>>k; 10 ll d = (1+2*k-1)*k/2; 11 ll t = n - d; 12 if(t>=0 && t%2 == 0) cout<<"YES"<<endl; 13 else cout<<"NO"<<endl; 14 } 15 return 0; 16 }
B. Princesses and Princes
贪心的去匹配每个Princesses当前可以匹配的最中意的Princes,如果存在没有匹配上的Princesses,随便和一个没有匹配过的Princes匹配即可。纯阅读理解题。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int main(){ 5 int t; 6 cin>>t; 7 while(t--){ 8 int n;cin>>n; 9 vector<int> v[n]; 10 int pr[n+1]; 11 int dr[n+1]; 12 memset(dr,0,sizeof(dr)); 13 memset(pr,0,sizeof(pr)); 14 for(int i = 1;i<=n;i++){ 15 int k;scanf("%d",&k); 16 for(int j = 0;j<k;j++){ 17 int t;scanf("%d",&t); 18 if(dr[i] == 0 && pr[t] == 0) pr[t] = 1,dr[i] = 1; 19 } 20 } 21 vector<int> r1,r2; 22 int f = 0; 23 for(int i = 1;i<=n;i++){ 24 if(dr[i] == 0) { 25 f = 1;r1.push_back(i); 26 } 27 if(pr[i] == 0) { 28 f = 1;r2.push_back(i); 29 } 30 } 31 if(f == 0){ 32 cout<<"OPTIMAL"<<endl; 33 } 34 else{ 35 cout<<"IMPROVE"<<endl; 36 for(int i = 0;i<r1.size();i++){ 37 cout<<r1[i]<<" "<<r2[i]<<endl; 38 break; 39 } 40 } 41 } 42 return 0; 43 }
C. Game with Chips
构造题。按最坏的情况考虑,直接先把所有的chips移动到一个角落里,然后从这个角落S形遍历一遍棋盘即可,这样必定可以经过棋盘上所有的关键点,整个操作必定不会超过2*m*n次,故不可能存在-1的情况。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 int main() 5 { 6 7 int n,m,k; 8 cin>>n>>m>>k; 9 for(int i=1;i<=k;i++) 10 { 11 int x,y;scanf("%d%d",&x,&y); 12 } 13 for(int i=1;i<=k;i++) 14 { 15 int x,y;scanf("%d%d",&x,&y); 16 } 17 int tn=0; 18 tn =tn+n-1+m-1+(n-1)*m+m-1; 19 cout << tn << endl; 20 for(int i=1; i<m; i++ ) 21 cout<<"L"; 22 for(int i=1; i<n; i++) 23 cout<<"U"; 24 for(int i=1; i<n; i++) 25 { 26 for(int j=1; j<m; j++) 27 if(i&1) 28 cout<<"R"; 29 else 30 cout<<"L"; 31 printf("D"); 32 } 33 for(int j=1; j<m; j++) 34 if (n&1) 35 printf("R"); 36 else 37 printf("L"); 38 39 return 0; 40 }
D. Infinite Path
一道定义在环上的排列幂定义题。p * p = p[ p [ i ] ] ,按照题目所给的定理可以轻易推导出从任意一p[i]出发,做排列幂运算之后最终回到p[i],把i和p[i]连边,这样可以构成一个环,而整个序列可以构成多个不相交环。对于一个环,从任意一点出发,走k步,也就是pk[i] ,会有c[i] = c[pk[i] ] ,也可能会有c[p2k[i] ]......,也就是说每次走从一点开始,相隔k个点,他们的c[i]是相等的,怎么求最小的k?当是从环长度的因子开始枚举,只有是因子k才能从某一起点开始,每次走k步,绕一圈回到这个起点。
预处理所有的环,然后枚举环,在环中枚举环长度的因子,再去检查环上是否存在合法的k,每次取k的最小值。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 2e5 +5; 5 int k,n,cnt,ans; 6 int p[maxn],c[maxn],vis[maxn],g[maxn]; 7 bool ok(int x,int y){ 8 for(int i = 1;i<=x;i++){//在长度为x的范围内枚举起点 9 int f = 0,t = i; 10 for(int j = 1;j<=y;j++){//整个环上有y个相隔x的点 11 if(c[g[t]] != c[g[i]]){//检查每次移动k步到的点,其c值是否相等。 12 f = 1;break; 13 } 14 t = (t + x - 1) %cnt + 1;//t是下一个点的位置 15 } 16 if(!f) return 1; 17 } 18 return 0; 19 } 20 void dfs(int x){ 21 cnt = 1; 22 g[cnt] = x,vis[x] = 1; 23 for(int i = p[x];i!=x;i=p[i]) vis[i] = 1,g[++cnt] = i;//从一点开始预处理环,结点存入g数组 24 for(int i = 1;i<=sqrt(cnt);i++){//枚举环长度cnt的因子 25 if(cnt%i == 0){ 26 if(ok(i,cnt/i)) {ans = min(ans,i);return;} //检查k = i是否合法 27 if(ok(cnt/i,i) )ans = min(ans,cnt/i);//检查k = cnt/i是否合法 28 } 29 } 30 } 31 int main() 32 { 33 int t; 34 scanf("%d",&t); 35 while(t--){ 36 scanf("%d",&n); 37 for(int i = 1;i<=n;i++) scanf("%d",&p[i]); 38 for(int i = 1;i<=n;i++) scanf("%d",&c[i]); 39 ans = 2e5+10; 40 for(int i = 1;i<=n;i++) vis[i] = 0; 41 for(int i = 1;i<=n;i++) { 42 if(!vis[i]) dfs(i); 43 } 44 cout<<ans<<endl; 45 } 46 return 0; 47 }
E. Count The Blocks
计数题。n位数,首先考虑block的长度为1,各个位置都可以放置0~10这样不同的数字,一共10个数字,对于其中1个位置,这个位置可以放10种可能的数字,其左右相邻的位放置9种可能的数,不相邻的其他位可以任意放置10个数字。
考虑长度n的数,block长度为k
1.左右两个端点对答案的贡献是2*10*9*10n-k-1 ,2是2个端点,10是端点可以放置10种可能的数,9是其相邻位置只能放9种可能,10n-k-1是其他点可以放置的数字有多少种。
2.中间的长度为k的段,10*9*9*10n-k-2,10是这一段放置10种可能的数字,2个9是这一段左右端点相邻的点要和段内数字不同,有9种可能,10n-k-2 是其他点可以放置的数字有多少种可能,这样的段一共有n-k-1个,再乘一下即可。
首先要预处理一下10的n次方。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const ll mod = 998244353; 5 const int maxn = 2e5+5; 6 ll n; 7 ll f[maxn]; 8 void pre(){ 9 f[1] = 10; 10 for(int i = 2;i<=n;i++){ 11 f[i] = f[i-1]*10%mod; 12 } 13 } 14 int main() 15 { 16 cin>>n; 17 pre(); 18 for(int i = 1;i<n;i++){ 19 ll d = n + 1 - i; 20 ll x = ((ll(2*9)*f[n-i])%mod + (ll(d-2)*9*9*f[n-i-1])%mod)%mod; 21 cout<<x<<" "; 22 } 23 cout<<10; 24 return 0; 25 }