我收回我之前说的可能不会更新了,迫切需要整理思路
思维现在真的是完全没有…了呢,写模拟题都fst。
之前其实没怎么打过CF,今天一打开想起自己还是?名(?介于蓝绿色间的那个),太惨了8,泪目。呜呜呜呜呜呜
A. Elections
题意:有n个学生,每人有k张选票。如果一个人给Elodreip投a[i]票,Awruk将得到k-a[i]票。问最小的k使得Awruk赢得选举。
用sum记录a[i]总和,k*n-sum>sum即赢得选举的条件。为了避免奇奇怪怪的问题出现,我选择直接枚举
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #define Max(a,b) (a>b?a:b) using namespace std; int main() { int n,sum=0,maxn=0,a; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a),sum+=a,maxn=Max(maxn,a); for(int i=maxn;;i++) { if(i*n-sum>sum){printf("%d\n",i);break;} } return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<vector> #include<algorithm> #define Max(a,b) (a>b?a:b) using namespace std; vector<int>v; int a[1005],n,ans=0; int main() { scanf("%d",&n),a[0]=0; for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=n;i;i--)a[i]-=a[i-1]; for(int i=1;i<=n;i++) { bool f=1; for(int j=1;;j++) { if(j+i>n)break; if(a[j]!=a[j+i]){f=0;break;} } if(f)v.push_back(i); } printf("%d\n",v.size()); for(int i=0;i<v.size();i++) printf("%d ",v[i]); return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #define Min(a,b) (a<b?a:b) #define MAXN 300003 #define Max(a,b) (a>b?a:b) #define LL long long using namespace std; char s[1002]; int main() { scanf("%s",s+1); int len=strlen(s+1); for(int i=1;i<len;i++) { if(s[i+1]==s[i])printf("0 "); else printf("1 "),swap(s[1],s[i]); } if(s[len]=='a')printf("1\n"); else printf("0\n"); return 0; }
题意:共有m个长度为n的字符串,现在可对每个字符串进行操作去掉它的前缀和后缀,使得所有字符串剩余部分相同,问有多少种方案
问题可以看做求所有字符串的公共子串的个数,我们知道如果一个字符串s在每个字符串里都出现,那这个子串的任意子串也都符合题意,这个字符串对ans的贡献是(1+|s|)*|s|/2
由于每个字符串都是1到n的排列,我们可以预处理出每个数字后的一个数字是否相同,辅助我们算出所有不能再拓展的串s,说到这里相信你已经能脑补出来了,具体实现还是看代码。
nxt[i][j]:第i个串数字j的下一个数字 f[i]:所有串中数字i的下一个数字(若下一位不相同则为-1) len[i]:以数字i开始的串最多可以拓展几位
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #define Min(a,b) (a<b?a:b) #define N 100002 #define M 12 #define Max(a,b) (a>b?a:b) #define LL long long using namespace std; int n,m,a[M][N],nxt[M][N],f[N],len[N]; LL ans=0; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) { scanf("%d",&a[i][j]); if(j-1)nxt[i][a[i][j-1]]=a[i][j]; if(j==m)nxt[i][a[i][j]]=-1; } } for(int i=1;i<=n;i++) { int same=nxt[1][i]; for(int j=2;j<=m;j++) if(nxt[j][i]!=same){same=-1;break;} f[i]=same; } for(int i=n;i;i--) { int num=a[1][i]; len[num]=1; if(f[num]!=-1)len[num]+=len[f[num]]; } for(int i=1;i<=n;i+=len[a[1][i]]) { int l=len[a[1][i]]; ans+=(1LL+l)*l/2; } printf("%I64d\n",ans); return 0; }
题意:共有n个参赛者,给出xi,yi分别为每个人参加第一场比赛与第二场比赛的得分。共有m组敌对关系,有敌对关系的人不会配合参加比赛。现在教练需要让所有没有敌对关系的人配合参加比赛(其中一人负责第一场,另一人第二场),最终得分越小越好。求每个人的得分
可以想到先统计所有人两两配合的最小分数,再减去有敌对关系组的分数。
两个人i,j比赛应使得分数为min{xi+yj,xj+yi}
xi+yj<xj+yi即xi-yi<xj-yj,故可以对xi-yi排序,则i的得分为xi*排在i后面的数个数+yi*排在i前面的数个数
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #define Min(a,b) (a<b?a:b) #define MAXN 300003 #define Max(a,b) (a>b?a:b) #define LL long long using namespace std; LL read() { LL x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } LL A[MAXN],B[MAXN]; struct Node{LL a,b,num;}p[MAXN]; LL presa[MAXN],presb[MAXN]; bool operator < (const Node x,const Node y) { return x.a-x.b<y.a-y.b; } LL ans[MAXN]; int main() { int n=read(),m=read(); for(int i=1;i<=n;i++) A[i]=p[i].a=read(),B[i]=p[i].b=read(),p[i].num=i; sort(p+1,p+1+n); presa[0]=0,presb[0]=0; for(int i=1;i<=n;i++) presa[i]=presa[i-1]+p[i].a,presb[i]=presb[i-1]+p[i].b; for(int i=1;i<=n;i++) { ans[p[i].num]=p[i].a*(n-i)+p[i].b*(i-1); ans[p[i].num]+=presb[n]-presb[i]; ans[p[i].num]+=presa[i-1]; } for(int i=1;i<=m;i++) { int x=read(),y=read(); ans[x]-=Min(A[x]+B[y],A[y]+B[x]); ans[y]-=Min(A[x]+B[y],A[y]+B[x]); } for(int i=1;i<=n;i++)printf("%I64d ",ans[i]); return 0; }