Sumdiv--数论+快速幂取模+唯一分解定理+欧拉筛

Sumdiv
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

The only line of the output will contain S modulo 9901.

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


又一道数论题,机智的我想到了快速幂取模和唯一分解定理,但愚蠢的我并不会把约数加和,无奈,半天也没想出来,只能又去题解。。。。

http://blog.csdn.net/rowanhaoa/article/details/8591077

这篇题解讲的很详细,如果没有看过唯一分解定理的人的话,建议去看一下百度文库,至于快速幂,我建议去看百科,讲的很好,有的时候确实能够从百科上学到好多东西。

至于加和的话,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
                  1+p+p^2+p^3+........+p^n=(1+p+p^2+....+p^(n/2-1))*(1+p^(n/2+1));

渣渣还要努力啊、

代码:

#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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值