Educational Codeforces Round 84 (Rated for Div. 2)
A. Sum of Odd Integers (CF 1327 A)
题目大意
给定,问是否能表示成个互不相同的奇数的和。
解题思路
首先和的奇偶性要相同,其次个互不相同的奇数的和的最小值为,所以需要
神奇的代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; int main(void) { int t; cin>>t; while(t--){ LL n,k; cin>>n>>k; bool qwq=false; if ((n-k)%2==0&&n>=k*k) puts("YES"); else puts("NO"); } return 0; }
B. Princesses and Princes (CF 1327 B)
题目大意
个公主与个王子配对,每个公主有几个王子的配对意愿。对于标号从小到大的每个公主,找公主有配对意愿的王子中最小编号的且未配对的与公主配对。问能否再增加一条配对意愿,使得最终得以配对的公主数增加,能则输出任意一条配对意愿。
解题思路
直接模拟,最后看是否个公主都配对了,不是则找一个未配对的公主和未配对的王子给他们增加一条配对意愿即可。
神奇的代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } int main(void) { int t; read(t); while(t--){ int n; read(n); bool sign[n+1]={0}; int dau=-1; for(int i=1;i<=n;++i){ int k; read(k); bool qwq=false; for(int u,j=1;j<=k;++j){ read(u); if (!qwq&&!sign[u]) {sign[u]=true; qwq=true;} } if (!qwq) dau=i; } if (dau==-1) puts("OPTIMAL"); else{ int cur=1; while(sign[cur]) ++cur; puts("IMPROVE"); printf("%d %d\n",dau,cur); } } return 0; }
C. Game with Chips (CF 1327 C)
题目大意
的网格,有个chips。给出了它们的初始位置,然后分别给出每个chip的特定位置,可以进行四种操作:上、下、左、右,即将全部chips向上、下、左、右移动一格,若对于移动会超出边界的chips则在原地不动。问能否在的操作次数内,使得每个chip都能至少达到特定位置一次,能则输出操作。
解题思路
一道滑稽构造题。把全部chips移动到左上角然后再遍历整个网格即可。操作数
神奇的代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; int main(void) { int n,m; cin>>n>>m; string s; string quq(n-1,'U'); string qlq(m-1,'L'); string qrq(m-1,'R'); s+=quq; s+=qlq; for(int ss=1,i=1;i<=n;++i){ if (ss==1){ s+=qrq; if (i!=n) s+='D'; ss^=1; }else{ s+=qlq; if (i!=n) s+='D'; ss^=1; } } int len=s.size(); cout<<len<<endl<<s<<endl; return 0; }
D. Infinite Path (CF 1327 D)
题目大意
给定一个排列,以及每个元素的颜色,同时定义排列的乘法,即,其中是两个排列。因此我们定义排列的次方。求一个最小的正整数,使得排列里存在一个无穷序列。所谓无穷序列就是,且
解题思路
很显然,如果有自环的话最小为。
一个排列所形成的置换形成一个个环,我们观察的次方的定义可知,一个个环之间是相互独立的,所以我们分别考察每个环,看看每个点的颜色是否都相同。
对于一个环来说,有个点,如果是,就相当于对于一个点,它往前一位选一个点,直到已经选到的点为止。而如果是,则它往前两位选一个点,直到已经选到的点为止。
如果选得好,一个环会被拆成个小环,而如果原来的大环不符合要求,而小环有可能符合要求。至于是哪些能把大环拆成小环,很容易得知当是的因数的话就能拆成小环。所以我们枚举的因数分别去判断是否可行,取最小值即可。
第一次在传参时vector没加&然后MLE……
神奇的代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } bool check(vector<int> &ji,int st,int step,int c[]){ for(size_t i=st+step;i<ji.size();i+=step){ if (c[ji[i]]!=c[ji[i-step]]) return false; } return true; } void work(vector<int> &ji,int c[],int &ans){ int cnt=ji.size(); int up=sqrt(cnt); for(int i=1;i<=up;++i){ if (cnt%i!=0) continue; for(int j=0;j<i;++j) if (check(ji,j,i,c)) { ans=min(ans,i); break; } if (i!=cnt/i) { for(int j=0;j<cnt/i;++j) if (check(ji,j,cnt/i,c)) { ans=min(ans,cnt/i); break; } } } } void DFS(int u,int nxt[],vector<int> &ji,int c[],bool sign[],int &ans){ sign[u]=true; ji.push_back(u); if (sign[nxt[u]]) work(ji,c,ans); else DFS(nxt[u],nxt,ji,c,sign,ans); } int main(void) { int t; read(t); while(t--){ int n; read(n); bool qwq=false; int nxt[n+1]={0}; for(int i=1;i<=n;++i){ read(nxt[i]); if (nxt[i]==i) qwq=true; } int c[n+1]={0}; for(int i=1;i<=n;++i){ read(c[i]); } if (qwq){ puts("1"); continue; } int ans=1e9+7; bool sign[n+1]={0}; for(int i=1;i<=n;++i){ if (!sign[i]) { vector<int> ji; DFS(i,nxt,ji,c,sign,ans); } } write(ans,'\n'); } return 0; }
E. Count The Blocks (CF 1327 E)
题目大意
给定,有个数字从到,包括前导零使得每个数字都有位。现在要分别统计长度从到的数字block的数量。所谓数字block指的是一串连续的相同数位,它不能再往左边或右边拓展(到边界了或者拓展后这串数位不是相同的)
解题思路
一开始以为是数位DP,稍加思索后发现,对于数字block长度为i的数量,分别考虑以每一位开始的长度为i的block对答案的贡献即可。
时,
时,
时,
神奇的代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } const LL mo=998244353; LL qpower(int a,int b){ LL aa=a; LL qwq=1; while(b){ if (b&1) qwq=qwq*aa%mo; aa=aa*aa%mo; b>>=1; } return qwq; } int main(void) { int n; read(n); for(int i=1;i<=n;++i){ LL ans=0; if (i<n-1) ans=(n-i-1)*81%mo*qpower(10,n-i-1)%mo; if (i==n) ans=10; else ans=(ans+18*qpower(10,n-i)%mo)%mo; write(ans); } return 0; }
F. AND Segments (CF 1327 F)
题目大意
给定,有个要求,表示为。先要求构造一个长度为的数组,满足
求满足上述两个要求的数组的数量模
解题思路
是位运算,我们注意到不同位之间是相互独立的,那么我们就分别计算每一位,每个数在该位的取值的所有情况,最后每一位之间相乘即可得到答案。
对于当前考虑的某一位,对于一个要求.
如果在该位是,那么在该位都一定是。
如果在该位是,那么在该位不能全是。
那么现在就要统计一个长度为的序列数量,该序列的每个数字是或,且有部分区间的数字全为,部分区间的数字不能全为。
注意到是极为特殊的数,我们设表示当前是第个数字,且这个数字为(或最后一个填的位置是)的方案数。
如果这个数字是一定为的,则
如果这个数字可以不为,我们则枚举上一个填的位置,由于到都是填的,我们不能让这个区间有 不能全为的区间,所以应该从到 不能全为的区间 的右端点小于的那些区间 的最大左端点,记为,即,所以。这个用前缀和维护就好了。
初始化dp[0]=1。
最后把所有位的dp[n+1]相乘即可。
神奇的代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } const LL mo=998244353; int main(void) { int n,m,k; read(n); read(k); read(m); vector<pair<pair<int,int>,int>> q(m); LL ans=1; for(int l,r,x,i=0;i<m;++i){ read(l); read(r); read(x); q[i]=make_pair(make_pair(l,r),x); } for(int i=0;i<k;++i){ int sign[n+5]={0}; int qwq[n+5]={0}; for(auto & j:q){ if (j.second&1){ sign[j.first.first]++; sign[j.first.second+1]--; }else{ qwq[j.first.second+1]=max(j.first.first,qwq[j.first.second+1]); } j.second>>=1; } LL sum[n+5]={0}; sum[0]=1; int cnt=0; int pos=0; for(int j=1;j<=n+1;++j){ cnt+=sign[j]; pos=max(pos,qwq[j]); if (cnt) sum[j]=sum[j-1]; else if (pos!=0) sum[j]=((sum[j-1]+sum[j-1])%mo-sum[pos-1]+mo)%mo; else sum[j]=(sum[j-1]+sum[j-1])%mo; } ans=((sum[n+1]-sum[n]+mo)%mo*ans)%mo; } write(ans,'\n'); return 0; }
本文作者:~Lanly~
本文链接:https://www.cnblogs.com/Lanly/p/12557669.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步