1. 程式人生 > >CSU OJ:1347 Last Digitn(找規律||找週期+快速冪)

CSU OJ:1347 Last Digitn(找規律||找週期+快速冪)

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;
}