题意
题目链接:1089. Happy 2004
这个题目就是求出
2004Xmod29
的结果,其中
1≤X≤10000000
Input
1
10000
0
Output
6
10
思路
明显暴力解法肯定会超时, 数论问题首先要从整数的标准分解入手:
N=∏ki=1paii 其中 pi 是N 的质因子, ai 为其次数。
例如:
12=22∗3
有了标准分解, 接着考虑 一个整数的是怎么构成因数的,就是由 质因子及其幂 相互相乘得到的,具体来说就是 我们每次可以取出
pi
的不同次数,来构成因数,这样就有
0,1,…ai
,共有(
ai
+1) 种选择。 接着就是一个组合过程,看下面的式子:
∏ki=1(p0i+p1i+…+paii)
这个式子展开之后就是 所有的因子相加了 ,正是我们所求的~
下面就是求解这个式子结果了, 取模的话就直接分配进去按照二分幂 取摸,
不过这里有个技巧:
∃l Al+xmod m=Axmod m 其中 l∈[0,m] 成立,
只需要求出循环节
l
<script type="math/tex" id="MathJax-Element-13">l</script> 即可, 最后加上余下的那部分数字即可。2004的质因子为2,3,167
2的幂关于29的循环节是28;
3的幂关于29的循环节是28;
167的幂关于29的循环节是21;
2,3,167的循环节内的和 mod 29 正好为0;
因此只需要求出 循环节剩下的部分即可~
代码
#include <iostream>
#include <math.h>
#include <stdlib.h>
using namespace std;
int n;
int main()
{
while(cin>>n&&n)
{
long long a=0,b=0,c=0,t=1;
for(int i=0; i<(2*n+1)%28;i++)
a+=(long long)(pow(2.0,i))%29;
for(int i=0;i<(n+1)%28;i++)
b+=(long long)(pow(3.0,i))%29;
for(int i=0;i<(n+1)%14;i++){// 这里没有直接使用pow 函数,考虑到pow(167,20) 会超范围
c+=t;
t*=167;
t%=29;
}
cout<<((a%29)*(b%29)*(c%29))%29<<endl;
}
}