spoj 10649 镜子数的统计(正过来反过去一样)
101为镜子数,100不是,并且121也不是,因为2反过来会变成s形,所以这题的思路只用考虑0,1,8也就是一个三进制的数就可以了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<cstdlib> 6 #include<algorithm> 7 using std::cout; 8 using std::endl; 9 using std::cin; 10 typedef long long LL; 11 int const N = 50; 12 LL dp[N],f[N]; 13 char tmp[N]; 14 void pre() 15 { 16 f[0]=1; 17 f[1]=3; 18 for(int i=2;i<=45;i++) 19 if(i&1)f[i]=f[i-1]*3; 20 else f[i]=f[i-1]; 21 dp[1]=3; 22 dp[2]=2; 23 for(int i=3;i<=45;i++) 24 if(i&1)dp[i]=dp[i-1]*3; 25 else dp[i]=dp[i-2]*3; 26 } 27 bool OK(char s) 28 { 29 return (s=='0'||s=='1'||s=='8'); 30 } 31 LL judge(char c,int len) 32 { 33 char str[50]; 34 int up=(len>>1); 35 for(int i=0;i<up;i++) 36 { 37 if(!OK(tmp[i]))return 0; 38 str[i]=str[len-i-1]=tmp[i]; 39 } 40 if(len&1)str[up]=c; 41 str[len]='\0'; 42 return strcmp(tmp,str)>=0; 43 } 44 LL getsum() 45 { 46 int len=strlen(tmp); 47 LL ans=0; 48 for(int i=1;i<len;i++)ans+=dp[i]; 49 int up=len>>1; 50 for(int i=0;i<up;i++) 51 { 52 LL sum=f[len-((i+1)<<1)]; 53 if(i&&tmp[i]>'0')ans+=sum; 54 if(tmp[i]>'1')ans+=sum; 55 if(tmp[i]>'8')ans+=sum; 56 if(!OK(tmp[i]))break; 57 } 58 if(len&1) 59 { 60 ans+=judge('0',len); 61 ans+=judge('1',len); 62 ans+=judge('8',len); 63 } 64 else 65 ans+=judge(0,len); 66 return ans; 67 } 68 int deal() 69 { 70 int len=strlen(tmp); 71 int up=(len>>1); 72 for(int i=0;i<up;i++) 73 { 74 if(!OK(tmp[i]))return 0; 75 if(tmp[i]!=tmp[len-1-i])return 0; 76 } 77 if(len&1) 78 if(!OK(tmp[up]))return 0; 79 return 1; 80 } 81 int main() 82 { 83 int T; 84 pre(); 85 scanf("%d",&T); 86 while(T--) 87 { 88 scanf("%s",tmp); 89 LL ans=getsum()-deal(); 90 scanf("%s",tmp); 91 ans=getsum()-ans; 92 cout<<ans<<endl; 93 } 94 return 0; 95 }