比赛链接: https://codeforces.com/contest/1316
A
题意:
给出n个同学的分数,和分数上限m,你可以修改1号同学的成绩,问:在满足n个同学的平均分不变 且 不超过分数上限的前提下,1号同学的成绩最大是多少。
思路:
平均分不变,即n个同学的总分s不变,答案就是min(s,m)。
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;
scanf("%d",&t);
while(t--){
int n,m,s=0,x;
scanf("%d%d",&n,&m);
for(int i=0;i<n;++i){
scanf("%d",&x);
s+=x;
}
printf("%d\n",min(m,s));
}
}
B
题意:
对于给出的字符串,输出经过“操作”之后,字典序最小的字符串,并输出“操作”的长度。
“操作”:对于长为n的字符串s,长度为k的操作是指:for i from 1 to n-k+1, reverse the substring s[i:i+k-1] of s。
思路:
先试几个,找规律
对于“lfpbavjsm” (n=9)
k=5: avjsmbpfl
k=4: bavjsmlfp
对于“qwerty” (n=6)
k=3: ertyqw
可以发现:当k=i时,操作的结果就是先把substring[i:n]移到前面,然后,如果k和n同奇或同偶,就把前面的子串逆序拼接到后面,否则原封不动拼接到后面。
证明:翻转操作执行的次数cnt=n-k+1, 如果cnt是偶数,那么substring[1:k-1](被调到最后的前缀)相当于没翻转,如果cnt是奇数,那就是翻转了。
所以,枚举k from 1 to n,执行“操作”,找所有结果中字典序最小的即可。
代码:
#include<bits/stdc++.h>
using namespace std;
string s;
int a[5005];
int main(){
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
cin>>s;
string ans=s;
int id=1;
for(int i=1;i<n;++i){
string s1=s.substr(0,i);
if((n-i)&1) reverse(s1.begin(),s1.end());
string s2=s.substr(i,n-i);
s2+=s1;
if(s2<ans){
ans=s2;
id=i+1;
}
}
cout<<ans<<endl<<id<<endl;
}
}
C
题意:
给两个“本原多项式”和一个模数p,求多项式乘积的各项系数中不能整除p的系数对应的项的指数。
思路:
https://blog.csdn.net/qq_43563669/article/details/104666878
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,m,p,x,I,J;
scanf("%d%d%d",&n,&m,&p);
for(int i=0;i<n;++i) {scanf("%d",&x); if(x%p!=0) I=i;}
for(int i=0;i<m;++i) {scanf("%d",&x); if(x%p!=0) J=i;}
printf("%d\n",I+J);
}
拓展:
设是唯一分解整环上的多项式,如果,则称为上的一个本原多项式。
高斯引理:本原多项式的乘积还是本原多项式。
但是此题给出这个条件是为什么呢,我还不是太明白。
PS:还有用强力fft板子把这题过掉的,等我找到就贴上来。