Codeforces Round #609 (Div. 2) A,B,C题详细题解
这次CF感觉是一个上分特别好的机会,可惜我英语太屎了,看不懂AB两题。。最后只AC了C题居然也能上分,一 题 涨 分 传 说。
A题:Equation
1.大概题意:
输入一个n,输出两个合数a,b使得a-b=n;
2.思路:
签到题,题目保证ab一定是存在的,而且只需要输出其中的一个特解即可。可以知道如果n是偶数或者0(即mod2后余数为0),那么它加上4之后一定是一个合数,同理如果n是奇数,那么它加上9之后一定会得到一个合数。
3.代码:
#include<iostream>
using namespace std;
int main(){
int n;
while(scanf("%d",&n)!=EOF){
if(n%2==0){
cout<<4+n<<' '<<4<<endl;//偶数+4必为合数
}
else{
cout<<9+n<<' '<<9<<endl;//奇数+9必为合数
}
}
return 0;
}
B题:Modulo Equality
1.大概题意:
先给两个数,1≤n≤2000,1≤m≤1e9,n是集合的元素数量,m是模数
给两个集合a,b,我们要找到一个最小的x解使得(a[i]+x)mod m==b[j],即a的每个元素加x再模m以后可以与b中的元素一一对应。
2.思路:
暴力枚举a[0]和b的每个元素的差模m。其实就是枚举a[0]是对应b中的哪一个,复杂度O(N)。
把a中的每个元素+x模m之后的数储存在c中并且对c排序,这样方便之后的比较。
还有就是用到了取模运算的分配率(a + b) % p = (a % p + b % p) % p
还有结合律((a+b) % p + c) % p = (a + (b+c) % p) % p
在这题中的体现就是(a[i]+x)%m=b[j]
通过移项变成x=(a[i]-b[j]+m)%m
3.看代码:
#include<iostream>
#include<algorithm>
using namespace std;
#define INF 0x7f7f7f7f
int a[2010],b[2010],c[2010];
int main(){
int flag,x,n,m,minx;
while(scanf("%d%d",&n,&m)!=EOF){
minx=INF;//因为是要找到最小的解,所以用minx保存
for(int i=0;i<n;i++) scanf("%d",&a[i]);
for(int i=0;i<n;i++) scanf("%d",&b[i]);
sort(b,b+n);//对b排序
for(int i=0;i<n;i++){
flag=1;
x=(b[i]-a[0]+m)%m;
for(int j=0;j<n;j++){
c[j]=(a[j]+x)%m;//通过加x模m得到新的集合c
}
sort(c,c+n);//对c进行排序,方便之后的比较
flag=1;
for(int i=0;i<n;i++){
if(c[i]!=b[i]){ //这边再检查c和b两个集合是不是相同的
flag=0;break;
}
}
if(flag) minx=min(x,minx);//如果确定了bc两个集合是一样的,则记录最小的x
}
cout<<minx<<endl;
}
return 0;
}
这题我其实参考的是队里洪某大佬的思路,如果要一对一枚举的话那么复杂度就要是O(N^2)了,枚举a[0]对应的元素其实就是枚举x。
C题:Long Beautiful Integer
1.大概题意:
给了数字长度n和循环的长度k*(2≤n≤200000,1≤k<n)*
把数字的每一位分成a[1],a[2],a[3]…a[n];
如果这个数字的每个位数之间满足a[i+k]=b[i],则称这串数字为美丽的数字。
2.思路:
我的思路是从最高k位找到循环,然后往后看是不是都是这样循环下去。
如果有a[i+k]!=b[i]的情况,这边分成两种:
一种是b[i]>a[i+k]的情况
那么就是可以直接加上去的,执行过这个之后我用flag记录是否进行过这种增加操作。如果进行过了这种增加操作,之后的b[i]<a[i+k]的情况就不用改变前面的循环了,也就是说之后的数字就可以*改变了,就把循环一次一次往下套。如果进入了这种无脑套的情况,用flag=1来记录。
另外一种是b[i]<a[i+k]的情况
考虑如果flag没有记录,则在循环的最后一位上加上1,如果进行过了这个操作,同理把flag变成1,之后的数字就可以随便改了。
这题还需要考虑如果循环在+1以后需要进位的情况。
3.看代码:
#include<iostream>
#include<cstring>
using namespace std;
char a[200010];
int main(){
int n,st,ch,k,flag;
while(scanf("%d%d",&n,&k)!=EOF){
flag=0;//flag用来记录
getchar();
for(int j=1;j<=n;j++){
scanf("%c",&a[j]);
}
st=1;ch=k+1;//st就是在循环的k位数字之间轮流来,ch是检查后面的数字是否依照循环?
while(a[ch]<=a[st]&&ch<=n){//如果是小于的情况,不需要改变的最后一位
if(a[ch]<a[st]&&flag==0){//进行过这种增加的操作之后用flag记录。
flag=1;
}
a[ch]=a[st];//把不符合的位数变成与循环对应的情况
st=st%k+1;ch++;
}
if(ch!=n+1){//如果出现了大于的情况,就是在中途退出了循环
if(flag==0){//如果没有进行过前面的增加操作,则循环的最后一位需要+1
a[k]++;
for(int i=k;i>=1;i--){
if(a[i]>'9'){//考虑进位的情况
a[i]='0';a[i-1]++;
}
else break;
}
}
st=1;ch=k+1;
while(ch<=n+1){
a[ch]=a[st];//无脑往下循环
st=st%k+1;ch++;
}
}
cout<<n<<endl;
for(int i=1;i<=n;i++){
cout<<a[i];
}
cout<<endl;
}
}
总结
这次cf队里好多人都涨分了。。自己还是队里分数最低的几个之一,希望自己能够快快涨分吧!
推荐阅读
-
Codeforces Round #657 (Div. 2) C题
-
Codeforces Round #277.5 (Div. 2)(C题)_html/css_WEB-ITnose
-
B. Nastya Is Playing Computer Games---(水题模拟)Codeforces Round #546 (Div. 2)
-
Codeforces Round #483 (Div. 2) (A+B+C+D)
-
Codeforces Round #662 (Div. 2) [ A , B ] 题解报告
-
Codeforces Round #249 (Div. 2) A B C_html/css_WEB-ITnose
-
Educational Codeforces Round 88 (Rated for Div. 2)C. Mixing Water[题解](数学)
-
【Codeforces Round#621 (Div. 1 + Div. 2)】B. Cow and Friend 题解
-
Orac and LCM(GCD/LCM/质因子分解/推导证明)Codeforces Round #641 (Div. 2) C题
-
Codeforces Round #281 (Div. 2) (A、B、C、D题)_html/css_WEB-ITnose