Educational Codeforces Round 75 (Rated for Div. 2)
A. Broken Keyboard (CF 1251 A)
题目大意
键盘按键,鬼畜点一按会出现两次。现给出按键结果,判断哪些键一定不鬼畜。
解题思路
看同个字母连续出现奇数次还是偶数次即可。
神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; 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 kase; read(kase); for (int i = 1; i <= kase; i++) { char s[508]; scanf("%s",s); set<char> qwq; int len=strlen(s); for(int i=0;i<len;++i){ if (s[i]==s[i+1]) ++i; else qwq.insert(s[i]); } for(auto i:qwq) putchar(i); puts(""); } return 0; }
B. Binary Palindromes (CF 1251 B)
题目大意
给了串串,可以任意交换任意对串中任意的数字任意多次,问最多能弄出多少个回文串。
解题思路
我们发现串长度是奇数的话一定可以自身交换成回文串,而如果是偶数的话,如果是偶数个和也可以自身交换成回文串,如果是奇数个和则不行,记这种串为。由于奇数长度的串可以与串进行交换使得变成回文串。故如果有奇数串则全部都可以变成回文串,如果没有奇数串,但有偶数个串,它们俩俩交换也可以是其都变成回文串,故有偶数个串则全部都可以变成回文串,有奇数个的话就只有一个不能变成回文串。
神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; 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 kase; read(kase); for (int ii = 1; ii <= kase; ii++) { int n; read(n); int cnt[2]={0}; int aa=0; for(int i=0;i<n;++i){ char s[58]; scanf("%s",s); int len=strlen(s); int qwq[2]={0}; for(int j=0;j<len;++j) ++qwq[s[j]-'0']; if (len&1){ if (qwq[0]&1) ++cnt[0]; else ++cnt[1]; } else if (qwq[0]&1) ++aa; } aa=aa&1; aa=max(aa-cnt[0]-cnt[1],0); int ans=n-aa; write(ans,'\n'); } return 0; }
C. Minimize The Integer (CF 1251 C)
题目大意
给了一串数字,相邻奇偶性不同的可以交换位置,问最小能交换出的数字是多少。
解题思路
奇偶性相同的数字不能交换,那么它们的相对位置不能发现变化,而不同的可以随便变。那么我们把奇数的单独拎出来,偶数的单独拎出来,两个指针分别指着奇数组和偶数组,然后每次取奇偶中最小的放回即可。
神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; 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 kase; read(kase); for (int i = 1; i <= kase; i++) { char s[400005]; scanf("%s",s); int len=strlen(s); vector<int> cnt[2]; for(int i=0;i<len;++i){ int qwq=s[i]-'0'; cnt[qwq&1].push_back(qwq); } auto l=cnt[0].begin(); auto r=cnt[1].begin(); while(len--){ if (l!=cnt[0].end()&&r!=cnt[1].end()){ if (*l<*r){ putchar(*l+'0'); ++l; } else{ putchar(*r+'0'); ++r; } }else if (l!=cnt[0].end()){ putchar(*l+'0'); l++; }else{ putchar(*r+'0'); ++r; } } puts(""); } return 0; }
D. Salary Changing (CF 1251 D)
题目大意
给个人发工资,每人有一个发工资的钱数的范围,要求确定一种发工资方案,使得所有人所得的工资的中位数最大,且发的工资总数不超过。
解题思路
很容易想到可以二分中位数,然后对于工资范围,如果,这种人肯定给,而对于,这种人也肯定发,至于,我们需要中位数为,就要有个人的工资大于等于,如果此时这种人数小于的话,还差个,我们给最大的个人发工资,剩下的都发即可。如果大于则全部发,然后增大继续找。
神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; 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(LL mid,vector<pair<LL,LL>> sol,int n,LL s){ int cnt=0; vector<LL> qwq; for(auto i:sol){ if (i.second<mid) s-=i.first; else if (i.first>=mid) ++cnt,s-=i.first; else qwq.push_back(i.first); } int m=(n+1)>>1; if (cnt>m) return 1; if (s<0) return 0; if (qwq.size()+cnt<m) return 0; sort(qwq.begin(),qwq.end()); int cou=qwq.size()-(m-cnt); for(int i=0;i<cou;++i) s-=qwq[i]; s-=(m-cnt)*mid; if (s<0) return 0; return 1; } int main(void) { int kase; read(kase); for (int i = 1; i <= kase; i++) { int n; LL s; read(n); read(s); vector<pair<LL,LL>> sol; for(int i=1;i<=n;++i){ LL l,r; read(l); read(r); sol.push_back(make_pair(l,r)); } LL l=0,r=1e9+7; LL ans=0; while(l<r){ LL mid=(l+r)>>1; if (check(mid,sol,n,s)) ans=mid,l=mid+1; else r=mid; } write(ans,'\n'); } return 0; }
E1 E2. Voting (Easy/Hard Version) (CF 1251 E1 E2)
题目大意
拉选票,有个人,第个人需要用金钱贿赂才会给你投票,或者看见有大于等于个人给你投票的话他也会给你投票。现在你需要所有人都给你投票,问最小需要多少钱。
解题思路
分别考虑枚举金钱,贿赂多少人后无果。但考虑到知道多少人给你投票的角度的话似乎可解,于是我们将人通过分组,对倒序枚举,对于每组来说有一个,此时的人都已经投票给你了,记为,再加上自己已经贿赂了个人,如果的,那这组人就归降于您,否则就需要再在的人中贿赂直到或都贿赂完,我们自然是贪心的找最小的那些人贿赂,用优先队列维护即可。
神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; 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 kase; read(kase); for (int i = 1; i <= kase; i++) { int n; read(n); int cnt[n+1]={0}; vector<int> money[n+1]; for(int p,m,i=1;i<=n;++i){ read(m); read(p); cnt[m]++; money[m].push_back(p); } priority_queue<int,vector<int>,greater<int>> qwq; LL ans=0; int by=0; for(int i=1;i<=n;++i) cnt[i]+=cnt[i-1]; for(int i=n-1;i>0;--i){ if (money[i].empty()) continue; for(int j:money[i]) qwq.push(j); if (cnt[i-1]+by>=i) continue; while(!qwq.empty()&&cnt[i-1]+by<i){ ans+=qwq.top(); qwq.pop(); ++by; } } write(ans,'\n'); } return 0; }
F. Red-White Fence (CF 1251 F)
题目大意
块白栅栏块红栅栏有各自高度,要求选出一个红栅栏和若干个白栅栏,排成一排,要求红栅栏高度最高,红栅栏左边的白栅栏(可以没有)高度严格递增,右边的白栅栏(可以没有)高度严格递减,且它们的周长为,有次周长询问,分别回答方案数。
解题思路
记红栅栏高度为,选了个白栅栏,这栅栏的周长为。
由于要严格递增或递减,对于长度相同有若干个的白栅栏只会用到两个,于是白栅栏就分成两种类型,一种是高度出现一次的,另一种是出现两次(及以上都归为两次)的。设红栅栏高度为,则高度小于的白栅栏中,高度出现一次的有个,出现两次的有个,要选个白栅栏。然后我们考虑方案数。
如果为零,方案数即为,但如果不为,对于这些数我们要考虑选个还是选个,选个还要考虑放左边还是放右边。我们可以这样处理,把这个出现两次的这些数的个数翻倍,一个表示把它放左边的,一个表示把它放右边的,那么对于这个数就有三种选择的情况,分别对应上面的三种。所以最终的方案数即为,这是个卷积形式,我们对于每一个红栅栏,构造多项式,,用加速,则这个红栅栏对答案的贡献为的系数。预处理答案后回答。总时间复杂度为。
随便找了个NTT模板
神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; 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 mod=998244353; const int maxn=3e5+8; int N,M,n,k,q,wi,bl; LL a[maxn*3],b[maxn*3],c[maxn*3],g,jie[maxn],jieinv[maxn],white[maxn],red[6],ans[5*maxn]; int cnt_white[maxn],cnt_black[maxn]; LL qpower(LL x, LL y){ LL res=1; while (y){ if (y&1) (res*=x)%=mod; (x*=x)%=mod; y>>=1; } return res; } LL inv(LL x){return qpower(x, mod - 2);} void NTT(LL *arr,int size,int type){ int rev[maxn*3]; rev[0]=0; for(int i=1;i<size;++i) rev[i]=(rev[i>>1]>>1)|((i&1)?(size>>1):0); for(int i=0;i<size;++i) if (rev[i]>i) swap(arr[i],arr[rev[i]]); for(int len=2;len<=size;len<<=1){ LL wn=qpower(g,(mod-1)/len); if(type==-1) wn=inv(wn); for(int i=0;i<size;i+=len){ LL w=1; for(int j=0;j<(len>>1);++j,w=w*wn%mod){ LL tmp1=arr[i+j],tmp2=arr[i+(len>>1)+j]*w%mod; arr[i+j]=tmp1+tmp2; arr[i+j+(len>>1)]=tmp1-tmp2; if(arr[i+j]>=mod) arr[i+j]-=mod; if(arr[i+j+(len>>1)]<0) arr[i+j+(len>>1)]+=mod; } } } if(type==-1) { LL t=inv(size); for(int i=0;i<size;++i) arr[i]=arr[i]*t%mod; } } LL C(int m,int n){ if (m>n) return 0; if (m<0||n<0) return 0; return jie[n]*jieinv[m]%mod*jieinv[n-m]%mod; } int main(void) { read(n); read(k); for(int u,i=1;i<=n;++i){ read(u); if (cnt_white[u]<2) white[++wi]=u,++cnt_white[u]; } for(int u,i=1;i<=k;++i){ read(u); if (cnt_black[u]==0) red[++bl]=u,++cnt_black[u]; } sort(white+1,white+1+wi); sort(red+1,red+1+bl); jie[0]=jie[1]=jieinv[1]=jieinv[0]=1; for(int i=2;i<=n;++i){ jie[i]=jie[i-1]*i%mod; jieinv[i]=inv(jie[i]); } for(int i=1;i<=bl;++i){ int pos=lower_bound(white+1,white+1+wi,red[i])-white; N=M=0; for(int j=1;j<pos;++j){ if (white[j]==white[j+1]) N+=2,++j; else ++M; } for(int j=0;j<=M;++j) a[j]=C(j,M)*qpower(2,j)%mod; for(int j=0;j<=N;++j) b[j]=C(j,N); ++M; ++N; int sz=1; g=3; while(sz<N+M) sz<<=1; NTT(a,sz,1); NTT(b,sz,1); for(int i=0;i<sz;++i) c[i]=a[i]*b[i]%mod; NTT(c,sz,-1); for(int j=0;j<max(pos,0);++j) ans[(red[i]<<1)+((j+1)<<1)]=(ans[(red[i]<<1)+((j+1)<<1)]+c[j])%mod; for(int j=0;j<sz;++j) a[j]=0; for(int j=0;j<sz;++j) b[j]=0; for(int j=0;j<sz;++j) c[j]=0; } read(q); for(int Q,i=1;i<=q;++i){ read(Q); write(ans[Q],'\n'); } return 0; }
本文作者:~Lanly~
本文链接:https://www.cnblogs.com/Lanly/p/12270915.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现