[bzoj1223] [HNOI2002]Kathy函数
首先由题解可得TAT,f(i)=i当且仅当i在二进制下为回文串。
那么问题就变成了1~n中有多少个二进制下的回文串。
把m转成2进制后就是正常的统计了= =。
f[i]表示二进制下,有多少个i位的回文串(包括前导0)。f[1]=f[2]=2,f[i]=f[i-2]*2.....也就是f[i]=2^((i+1)/2)
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #define ri register int 6 using namespace std; 7 const int modd=1000000000; 8 char s[103]; 9 int two[340][20]; 10 int a[20],l[340],len,len2,mp[340],ten[10]; 11 int i,j,k,n,m; 12 int ans[20],ansl; 13 14 inline bool notsmall(int x){ 15 if(l[x]!=len)return l[x]>len; 16 for(ri i=len;i;i--)if(two[x][i]!=a[i])return two[x][i]>a[i]; 17 return 1; 18 } 19 inline bool notbig(int x){ 20 if(l[x]!=len)return l[x]<len; 21 for(ri i=len;i;i--)if(two[x][i]!=a[i])return two[x][i]<a[i]; 22 return 1; 23 } 24 inline void add(int x){ 25 l[x]=l[x-1];int y=x-1; 26 for(ri i=1;i<=l[x];i++){ 27 two[x][i]+=two[y][i]<<1; 28 if(two[x][i]>=modd)two[x][i]-=modd,two[x][i+1]++; 29 } 30 if(two[x][l[x]+1])l[x]++; 31 } 32 inline void addtoans(int x){ 33 for(ri i=1;i<=l[x];i++){ 34 ans[i]+=two[x][i]; 35 if(ans[i]>=modd)ans[i+1]++,ans[i]-=modd; 36 } 37 while(ans[ansl+1])ansl++; 38 } 39 inline void dec(int x){ 40 for(ri i=1;i<=l[x];i++){ 41 a[i]-=two[x][i]; 42 if(a[i]<0)a[i]+=modd,a[i+1]--; 43 } 44 while(!a[len]&&len>1)len--; 45 } 46 inline void run(){ 47 ri i,j,k,len; 48 two[1][l[1]=1]=1; 49 for(i=1;!notsmall(i);)i++,add(i); 50 for(;i;i--) 51 if(notbig(i))dec(i),mp[i]=1,len2=max(len2,i); 52 // for(i=len2;i;i--)printf(" %d",mp[i]);puts(""); 53 for(i=1;i<len2;i++)addtoans((i+1)>>1); 54 int flag=3; 55 for(i=len2>>1;i;i--)swap(mp[i],mp[len2-i+1]); 56 for(i=2;i<=len2&&flag;i++){ 57 if(mp[i]){ 58 if(i<=(len2>>1))addtoans((len2-(i<<1)+3)>>1); 59 else{ 60 if(mp[len2-i+1]==0||len2-i+1==i)addtoans(1); 61 } 62 } 63 if(i>(len2>>1))flag&=(mp[len2-i+1]==mp[i]); 64 } 65 if(flag==1||len2==1)addtoans(1); 66 } 67 int main(){ 68 scanf("%s",s);j=strlen(s); 69 for(i=ten[0]=1;i<=9;i++)ten[i]=ten[i-1]*10; 70 for(i=j-1;i>=0;i--){ 71 if(!k)len++; 72 a[len]+=(s[i]-'0')*ten[k]; 73 k++;if(k>8)k=0; 74 } 75 run(); 76 for(printf("%d",ans[ansl]),i=ansl-1;i>0;i--){ 77 for(j=10;j<modd;j*=10)if(ans[i]<j)putchar('0'); 78 printf("%d",ans[i]); 79 }puts(""); 80 return 0; 81 }
代码又丑又慢>_<