InputThe first line of the input contains an integer T (1<=T<=50) which means the number of test cases.
For each test cases, there is only one line that is the original integer N. we will ensure that N is an positive integer without leading zeros and N is less than 10^100000.OutputFor each test case, please output a line which is "Case X: L E G", X means the number of the test case. And L means the number of integers is less than N that we can get by revolving digits. E means the number of integers is equal to N. G means the number of integers is greater than N.Sample Input
1 341
Sample Output
Case 1: 1 1 1
题意:给定一个数字,问旋转后有多少个不同的数字小于它本身,等于它本身,大于它本身。
思路:比较两个数的大小时,我们可以跳过前面相等的数字,直接比较第一个不相等的数字,那么就可以用exKMP,得到expand的位置,然后比较第一个不相等的位置。因为是求不同的数字的贡献,我们还要注意循环节。
#include<bits/stdc++.h> using namespace std; const int maxn=201010; int Next[maxn],ans1,ans2,ans3; char c[maxn]; void exKMP(){ int i,len=strlen(c+1); Next[1]=len; for(int i=1;i<=len;i++) c[i+len]=c[i]; for(i=0;i+1<len+len&&c[i+1]==c[i+2];i++); Next[2]=i; int a=2; for(int k=3;k<=len+len;k++){ int p=a+Next[a]-1, L=Next[k-a+1]; if(L>=p-k+1){ int j=(p-k+1)>0?(p-k+1):0; while(k+j<=len+len&&c[k+j]==c[j+1]) j++; Next[k]=j, a=k; } else Next[k]=L; } ans1=ans2=ans3=0; for(int i=1;i<=len;i++){ if(Next[i]>=len){ if(ans2) break; ans2++; } else { if(c[i+Next[i]]<c[Next[i]+1]) ans1++; else ans3++; } } } int main(){ int T,Cas=0; scanf("%d",&T); while(T--){ scanf("%s",c+1); exKMP(); printf("Case %d: %d %d %d\n",++Cas,ans1,ans2,ans3); } return 0; }