您的位置:首页 > 其它

hdu 2837 Calculation 数论

2014-05-28 00:12 369 查看


Calculation

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1417    Accepted Submission(s): 292


Problem Description

Assume that f(0) = 1 and 0^0=1. f(n) = (n%10)^f(n/10) for all n bigger than zero. Please calculate f(n)%m. (2 ≤ n , m ≤ 10^9, x^y means the y th power of x).

 

Input

The first line contains a single positive integer T. which is the number of test cases. T lines follows.Each case consists of one line containing two positive integers n and m.

 

Output

One integer indicating the value of f(n)%m.

 

Sample Input

2
24 20
25 20

 

Sample Output

16
5

 

直接幂运算取模会超时,10^9摆在这。

数论,用到了快速幂,当然有一个公式A^x = A^(x % Phi(C) + Phi(C)) (mod C),【指数循环节】

该公式的证明:http://hi.baidu.com/aekdycoin/item/e493adc9a7c0870bad092fd9

//A^x = A^(x % Phi(C) + Phi(C)) (mod C)
#include<stdio.h>
#define LL long long

LL BitLength(LL x)//求x的二进制长度
{
LL d = 0;
while (x > 0)
{
x >>= 1;
d++;
}
return d;
}

LL BitAt(LL x, LL i)//返回x的二进制表示中从低到高的第i位
{
return ( x & (1 << (i-1)) );
}

LL Modular_Expoent(LL a,LL b,LL n)//求形如a^b%n的值
{
LL i, y=1;
for (i = BitLength(b); i > 0; i--)
{
y = (y*y)%n;
if (BitAt(b,i) > 0)
y = (y*a)%n;
}
return y;
}

LL phi(LL n)//素数筛选函数,返回小于n的素数个数
{
LL i,m=n;
for(i=2;i*i<=n;i++)
{
if(n%i==0)
{
m=m-m/i;
while(n%i==0) n/=i;
}
}
if(n>1)
m=m-m/n;
return m;
}

LL check(LL a,LL b,LL p)//保证a^b>=p
{
LL i,ans=1;
for(i=1;i<=b;i++)
{
ans*=a;
if(ans>=p)
return ans;
}
return ans;
}

LL f(LL n,LL m)//注意数据溢出
{
LL p=phi(m);
if(n<10)
return n;
LL x=f(n/10,p);
LL y=check(n%10,x,m);
if(y>=m)
{
LL ans=Modular_Expoent(n%10,x+p,m);
if(ans==0)
ans+=m;
return ans;
}
else
return y;
}

int main()
{
LL n,m,t;
while(scanf("%I64d",&t)!=EOF)
while(t--)
{
scanf("%I64d %I64d",&n,&m);
printf("%I64d\n",f(n,m)%m);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm hdu 数学 数论