题目大意:
题目传送门:https://codeforces.com/contest/1269/problem/C
给你一个由n个数字组成的大整数和一个k值,想请你找到大于等于这个数字的最小的由k个数字循环组成的数,并输出它的位数和它的值。比如样例2中:给定的数字为1234,k=2,则满足题意的数值应该为1313(1313是大于等于1234的最小的由k=2个数字1和3循环组成的数)。
题目分析:
这个题的难点在于找最小值。因为数字的范围太大,所以要用字符数组去保存这个整数,咱们不妨先令一个数等于所给数的前k位循环组成的数,位数和原数字相同。还用样例2举例,咱们不妨先令一个数为1212(前k=2位循环组成的位数和原数字一样的数),然后比较它和原数的大小,如果其大于等于原数,直接按要求输出即可。否则的话,让循环的数的最后一个数字+1。这里就要详细说一下了,假如这个数由k个数(编号分别为a0,a1……,ak-1)循环构成,那么当我们需要调整大小来使得循环数大于等于原数的时候,我们只需要调整ak-1就行了,因为这样做对原循环数的改变最小,从而满足题目要求的“最小”。
AC代码
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<set>
#include<string>
#define PI 3.1415926
typedef long long ll;
using namespace std;
static char s[2000010];
static char s2[2000010];
int main()
{
ll n=0,k=0;
cin>>n>>k;
cin>>s;
for(ll i=0;i<n;i++)
s2[i]=s[i%k];//先找出来循环数
if(strcmp(s2,s)>=0)//判断一下循环数和原数哪个大,注意这个函数的用法,谁在前谁在后
{//如果循环数比原数大或者相等的时候就直接按要求输出
cout<<strlen(s2)<<endl;
printf("%s\n",s2);
return 0;
}
s2[k-1]++;//如果循环数小于原数,调整循环节的最后一位数字,使其+1
ll t=k-1;
while(s2[t]-'0'>=10)//考虑进位的情况
{
s2[t]='0';
t--;
s2[t]++;
}
for(ll i=0;i<n;i++)
s2[i]=s2[i%k];//更新一下循环数
cout<<strlen(s2)<<endl;
printf("%s\n",s2);
return 0;
}
注意事项
1、C++中的string能存的字符数量是有限制的,当字符数量比较大的时候,还是开静态的字符数组或者全局变量字符数组好使,前几次写的超时就是因为这个。
2、注意考虑进位的情况,进位后这个位直接置0就可以。
3、注意strcmp()函数的用法。
4、别忘了最后再更新一下s2。