Sumdiv--數論+快速冪取模+唯一分解定理+尤拉篩
阿新 • • 發佈:2018-12-31
Sumdiv
The only line of the output will contain S modulo 9901.
The natural divisors of 8 are: 1,2,4,8. Their sum is 15.
15 modulo 9901 is 15 (that should be output).
若n為奇數,一共有偶數項,設p為3,則(1+p)+(p^2+p^3)=(1+p)+p^2(1+p)=(1+p^2)*(1+p) 1+p+p^2+p^3+........+p^n=(1+p+p^2+....+p^(n/2))*(1+p^(n/2+1));
若n為偶數,一共有奇數項,設p為4,則(1+p)+p^2+(p^3+p^4)=(1+p)+p^2+p^3(1+p)=(1+p^3)*(1+p)+P^2
1+p+p^2+p^3+........+p^n=(1+p+p^2+....+p^(n/2-1))*(1+p^(n/2+1));
Time Limit: 1000MS | Memory Limit: 30000K |
Total Submissions: 18987 | Accepted: 4767 |
Description
Consider two natural numbers A and B. Let S be the sum of all natural divisors of A^B. Determine S modulo 9901 (the rest of the division of S by 9901).Input
The only line contains the two natural numbers A and B, (0 <= A,B <= 50000000)separated by blanks.Output
Sample Input
2 3
Sample Output
15
Hint
2^3 = 8.The natural divisors of 8 are: 1,2,4,8. Their sum is 15.
15 modulo 9901 is 15 (that should be output).
題目連結:http://poj.org/problem?id=1845
又一道數論題,機智的我想到了快速冪取模和唯一分解定理,但愚蠢的我並不會把約數加和,無奈,半天也沒想出來,只能又去題解。。。。
這篇題解講的很詳細,如果沒有看過唯一分解定理的人的話,建議去看一下百度文庫,至於快速冪,我建議去看百科,講的很好,有的時候確實能夠從百科上學到好多東西。
至於加和的話,kuangbin大大寫的挺清楚地,偷學一下:
等比數列1+pi+pi^2+pi^3+...+pi^n可以由二分求得(即將需要求解的因式分成部分來求解)若n為奇數,一共有偶數項,設p為3,則(1+p)+(p^2+p^3)=(1+p)+p^2(1+p)=(1+p^2)*(1+p) 1+p+p^2+p^3+........+p^n=(1+p+p^2+....+p^(n/2))*(1+p^(n/2+1));
若n為偶數,一共有奇數項,設p為4,則(1+p)+p^2+(p^3+p^4)=(1+p)+p^2+p^3(1+p)=(1+p^3)*(1+p)+P^2
渣渣還要努力啊、
程式碼:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#define mod 9901
using namespace std;
int a[200000];
int b[200000];
int f[100000][10];
int k;
void prime()//尤拉篩
{
memset(a,0,sizeof(a));
int top=0;
int i;
for(i=2;i<=100000;i++)
{
if(a[i])
continue;
b[top++]=i;
for(int j=i*2;j<=100000;j+=i)
{
a[i]=1;
}
}
}
void fenjie(long long n)//唯一分解定理
{
k = 0;
int i;
memset(f, 0, sizeof(f));
for (i = 0; b[i] <= n/b[i]; i++)
{
if (n % b[i] == 0)
{
f[k][0] = b[i];
while (n % b[i] == 0)
{
f[k][1]++;
n /= b[i];
}
k++;
}
}
if (n != 1)
{
f[k][0] = n;
f[k++][1] = 1;
}
}
long long powc(long long x, long long n)//快速冪取模
{
long long res = 1;
long long tmp = x % mod;
while (n)
{
if (n & 1)
{
res *= tmp;
res %= mod;
}
n >>= 1;
tmp *= tmp;
tmp %= mod;
}
return res;
}
long long sum(long long p, long long n)//好吧,這個加和我還是不太很懂
{
if (p == 0)
{
return 0;
}
if (n == 0)
{
return 1;
}
if (n & 1)//奇數的情況
{
return ((1 + powc(p, n / 2 + 1)) % mod * sum(p, n / 2) % mod) % mod;
}
else//偶數的加和
{
return ((1 + powc(p, n / 2 + 1)) % mod * sum(p, n / 2 - 1) + powc(p, n / 2) % mod) % mod;
}
}
int main()
{
int n, m;
prime();
int i;
while (~scanf("%d%d", &n, &m))
{
fenjie(n);
long long ans = 1;
for (i = 0; i < k; i++)
{
ans *= (sum(f[i][0], m * f[i][1]) % mod);//約數加和
ans %= mod;//約數取模
}
cout << ans << endl;
}
return 0;
}