[poj] 2720 Last Digits

原题

其实简单的模拟就好了,不过我们要知道一个性质
要做无溢出的快速幂
(a^b mod m) =
if   (b < phi(m))    (a^b mod m)
else   (a^{bmod phi(m) + phi(m)} mod m)

然后因为输入组数很多,所以预处理一下是否有溢出,有的话就现算,否则直接输出

#include<cstdio>
typedef long long ll;
using namespace std;
ll b,n,l,a[100],g,ans,f[110][110];

inline ll ksm(ll x,ll y,ll mod)
{
    if (!y) return 1;
    if (y&1) return ksm(x*x%mod,y>>1,mod)*x%mod;
    return ksm(x*x%mod,y>>1,mod)%mod;
}

inline ll chck(ll x,ll y)
{
    if (y==-1) return -1;
    ll ans=1;
    for (int i=1;i<=y;i++)
    {
	ans*=x;
	if (ans>=a[7]) return -1;
    }
    return ans;
}

inline ll phi(ll x)
{
    ll ans=x,c=x;
    for (int i=2;i<=c/i;i++)
    {
	if (c%i==0) ans=ans/i*(i-1);
	while(c%i==0) c/=i;
    }
    if (c>1) ans=ans/c*(c-1);
    return ans;
}

inline void init()
{
    a[0]=1;
    for (int i=1;i<=7;i++) a[i]=a[i-1]*10;
    for (int i=0;i<=100;i++) f[1][i]=1;
    for (int i=2;i<=100;i++)
    {
	f[i][0]=1;
	for (int j=1;j<=100;j++)
	    f[i][j]=chck(i,f[i][j-1]);
    }
}

inline ll count(ll b,ll i,ll mod)
{
    if (mod==1) return 0;
    if (!i) return 1;
    if (f[b][i]<0)
    {
	int g=phi(mod);
	return ksm(b,count(b,i-1,g)+g,mod);
    }
    return f[b][i]%mod;
}

int main()
{
    init();
    while(~scanf("%lld",&b))
    {
	if (!b) break;
	scanf("%lld%lld",&l,&n);
	if (f[b][l]<0) f[b][l]=count(b,l,a[7]);
	ans=f[b][l]%a[n];
	for (int j=n;j>=1;j--)
	    if (ans/a[j-1]) break;
	    else putchar('0');
	if (ans) printf("%lld
",ans);
	else putchar('
');
    }
    return 0;
}
原文地址:https://www.cnblogs.com/mrha/p/7929981.html