您的位置:首页 > 移动开发

HDU 1452 Happy 2004 (唯一分解定理 + 求等比数列前n项和)

2015-09-10 00:09 447 查看
题目大意:先求2004^X 的因子和sum , 然后求sum%29.

同POJ 1845 类似。 先将2004分解成素数的乘积。然后对于2004^X , 改写成

p1^(q1*X) * p2^(q2*X) * ... * pn^(qn*X)


从而知道2004^X的因子的和为

(1+p1+p1^2+...+p1^(q1*X)) * (1+p2+p2^2+...+p2^(q2*X)) * ... * (1+pn+pn^2+...+pn^(qn*X))


然后用分治法求等比数列的前N项和即可

代码

#include <iostream>

using namespace std;
typedef long long ll;
const int maxn = 100;
int p[maxn] , q[maxn] , cnt;

void Init()
{
int a = 2004;
cnt = 0;
// 唯一分解定理
for(int i = 2; i * i <= a && a != 1; i++) if(a % i == 0) {
p[cnt] = i , q[cnt] = 0;
while(a % i == 0) {q[cnt]++; a /= i;}
cnt++;
if(i != 2) i++;
}
if(a != 1) {p[cnt] = a; q[cnt++]=1;}
}

// 求a^n % m
ll pow_mod(ll a , ll n , ll m)
{
if(n == 0) return 1;
ll x = pow_mod(a , n >> 1 , m);
ll ret = x * x % m;
if(n & 1) ret = ret * a % m;
return ret;
}

//求(1 + a + a^2 + ... + a^n) % m
ll sum(ll a , ll n , ll m)
{
if(!n) return 1;
if(n == 1) return a % m;
ll ret = 0;
if(n&1) {
ret = (1 + pow_mod(a , (n - 1) / 2 + 1 , m)) % m;
ret = (ret * sum(a , (n - 1) / 2 , m)) % m;
ret = (ret + pow_mod(a , (n - 1) / 2 + 1 , m)) % m;
}
else {
ret = (1 + pow_mod(a , n / 2 , m)) % m;
ret = (ret * sum(a , n / 2 , m)) % m;
}
return ret;
}
int main()
{
Init();
int n;
while(cin >> n && n)
{
ll ans = 1 , mod = 29;
for(int i = 0; i < cnt; i++) {
ll tmp = (sum(p[i] , q[i] * n , mod) + 1) % mod;
ans = (ans * tmp) % mod;
}
cout << ans << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: