1347: Last Digit
Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 261 Solved: 161Description
The function f(n, k) is defined by f(n, k) = 1k + 2k + 3k +...+ nk. If you know the value of n and k, could you tell us the last digit of f(n, k)?
For example, if n is 3 and k is 2, f(n, k) = f(3, 2) = 12 + 22 + 32 = 14. So the last digit of f(n, k) 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 n, k (1 <= n, k <= 109), which have the same meaning as above.
Output
For each test case, print the last digit of f(n, k) in one line.
Sample Input
10 1 1 8 4 2 5 3 2 5 2 8 3 2 4 7 999999997 999999998 2 1000000000 1000000000
Sample Output
1 2 3 4 5 6 7 8 9 0
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;
}