这个题目有很多高手都讨论过了,不过都不够详细,我就谈谈怎样解的吧。
开始我用的是模拟,这样有3个是超时的,于是我就手工模拟,比如:
a b c d e f
a+b b+c c+d d+e e+f
a+2b+c b+2c+d c+2d+e d+2e+f
a+3b+3c+d b+3c+3d+e c+3d+3e+f
a+4b+6c+4d+e b+4c+6d+4e+f
我们居然看到了熟悉的杨辉三角,熟悉二项式定理的人都知道,每一项的系数是C(0,n-2),C(1,n-2),...,C(n-2,n-2),而我们的问题就是求这些系数的个位。
如果直接计算,时间和空间都不够,不过我们可以发现,C(i,n-2)/C(i-1,n-2)=(n-i-1)/i,再利用某些人说的分解法就行了。我的方法是把n-i-1和i中的所有2和5提取出来单独处理,然后求解个位。容易看到,两个已知个位的奇数的商的个位是一定的(不过5的倍数会造成干扰)。
因此,程序就出来了,容易得知这个算法的复杂度为O(NlogN).以下程序在10个测试点中均只用了不到100ms:
- #include <stdio.h>
- #include <string.h>
- int f(int m,int n)
- {
- if (n==1) return m;
- if (n==3)
- switch (m)
- {
- case 1:return 7;
- case 3:return 1;
- case 7:return 9;
- case 9:return 3;
- }
- if (n==7)
- switch (m)
- {
- case 1:return 3;
- case 3:return 9;
- case 7:return 1;
- case 9:return 7;
- }
- if (n==9)
- switch (m)
- {
- case 1:return 9;
- case 3:return 7;
- case 7:return 3;
- case 9:return 1;
- }
- }
- int main()
- {
- char a[100004];
- int s,n,i,n2=0,n5=0,r=1,t1=0,t2=0,c[4]={6,2,4,8},tmp1,tmp2,tmp3;
- scanf("%s",a);
- n=strlen(a);
- for (i=0;i<n;i++) a[i]-='0';
- t1=a[0]+a[n-2];
- t2=a[1]+a[n-1];
- for (i=1;i<=n/2-1;i++)
- {
- tmp1=n-i-1;tmp2=i;
- while (tmp1%2==0) {n2++;tmp1/=2;}
- while (tmp1%5==0) {n5++;tmp1/=5;}
- while (tmp2%2==0) {n2--;tmp2/=2;}
- while (tmp2%5==0) {n5--;tmp2/=5;}
- r*=tmp1;
- r=f(r%10,tmp2%10);
- if (n5!=0)
- {
- if (n2!=0) tmp3=0;
- else tmp3=5;
- }
- else if (n2!=0) tmp3=r*c[n2%4]%10;
- else tmp3=r;
- t1+=(a[i]+a[n-2-i])*tmp3;
- if (t1>10000000) t1%=10;
- t2+=(a[i+1]+a[n-1-i])*tmp3;
- if (t2>10000000) t2%=10;
- }
- if (n%2==0)
- {
- i--;t1+=1000;t2+=1000;
- t1-=a[i]*tmp3;
- t2-=a[i+1]*tmp3;
- }
- t1%=10;t2%=10;
- s=t1*10+t2;
- if (s==0) s=100;
- printf("%d",s);
- }
总结——出现错误时需要换个思想纸上验证