CSU OJ:1347 Last Digitn(找规律||找周期+快速幂)

来源:互联网 发布:网络系统安全管理制度 编辑:程序博客网 时间:2024/06/05 04:19

1347: Last Digit

        Time Limit: 1 Sec     Memory Limit: 128 Mb     Submitted: 261     Solved: 161    

Description

    The function f(nk) is defined by f(nk) = 1k + 2k + 3k +...+ nk. If you know the value of n and k, could you tell us the last digit of f(nk)?
    For example, if n is 3 and k is 2, f(nk) = f(3, 2) = 12 + 22 + 32 = 14. So the last digit of f(nk) is 4.

Input

    The first line has an integer T (1 <= T <= 100), means there are T test cases.
    For each test case, there is only one line with two integers nk (1 <= nk <= 109), which have the same meaning as above.

Output

    For each test case, print the last digit of f(nk) in one line.

Sample Input

101 18 42 53 25 28 32 47 999999997999999998 21000000000 1000000000

Sample Output

1234567890

Hint

Source

中南大学第一届长沙地区程序设计邀请赛

解题思路:这种题一般都有周期,我把它的前200*200的表打了出来,发现它的列周期为4,行周期为100.这么一来,把他的100*4的表暴力写出来,然后对于n,k取余然后映射到打好的表即可。

代码如下:

#include <cstdio>int m[101][5];int quickpow(int a,int b){int ans=1;int base=a%10;while(b){if(b&1){ans=(ans*base)%10;}base=(base*base)%10;b=(b>>1);}return ans;}int main(){for(int n=1;n<=100;n++){for(int k=1;k<=4;k++){for(int i=1;i<=n;i++){m[n][k]=(m[n][k]+quickpow(i,k))%10;}}}/*for(int i=1;i<=200;i++)//打表后发现横着的循环节长度为4,纵向的循环节长度为100 {for(int j=1;j<=4;j++){printf("%d ",m[i][j]);}printf("\n");}*/int t;scanf("%d",&t);while(t--){int n,k;scanf("%d%d",&n,&k);if(n>100){n=n%100;}if(n==0)//比如n刚开始为200,那么它对应表中的100,但是取余时变成了0 {n=100;}if(k>4){k=k%4;}if(k==0)//同上 {k=4;}printf("%d\n",m[n][k]);}return 0;}

上面这种方法是离线打表的,比较快。还有网上的一种方法是找具体每次输入的n,k先打个大概的表,然后找表所对应的循环节,然后映射到打好的表输出答案:

/*该代码来自http://blog.csdn.net/aaaaacmer/article/details/44754637*/ #include<stdio.h>#include<string.h>int powermod(int a,int b){    int ans=1;    a=a%10;    while(b>0)    {        if(b%2==1)ans=(ans*a)%10;        b=b/2;        a=(a*a)%10;    }    return ans;}int main(){    int n,k,i,j,f[1111],T,flag,x,temp;    scanf("%d",&T);    while(T--)    {        memset(f,0,sizeof(f));        scanf("%d%d",&n,&k);        for(i=1;i<=1000;i++)//打个大概的表         {            f[i]=(f[i-1]+powermod(i,k))%10;        }        for(i=1;i<=1000;i++)//枚举循环节长度         {            flag=1;            for(j=i+1;j<=1000;j++)//判断所枚举的循环节是否正确             {                if(f[j%i]!=f[j]){                    flag=0;break;                }            }            if(flag){                x=i;break;            }        }    f[0]=f[x];//避免整除的那种   temp=n%x;//找到对应表中的位置         printf("%d\n",f[temp]);    }    return 0;}


0 0