POJ 1845 Sumdiv

题目大意

给你两个数A,B(≤5*10^7),求A^B的所有约数之和(mod 9901)

解题思路

显然把A的所有质因数(p1,p2,......,pn)和质因数的最高幂次(k1,k2,......,kn)求出来之后求sigma(pi^0+pi^1+......+pi^(ki * B))并取模,即为题目所求
我的思路有两个错误。
一开始想用线性筛质数乱搞,结果发现内存不够。此题是2002年的题目,应该还没用到这么屌的东西- -
第二个错误,等比数列求和中有除法运算,除法不满足同余运算的各种运算律,如果要满足需要转化为逆元,但转化为逆元的条件是将要除的数与取模的数互质,这道题明显不保证一定互质。
看了网上别人的解题报告,用到的是二分法求等比数列之和,这个可以有!

Code

#include <iostream>
#include <cstdio>
#include <cmath>

using namespace std;

const int p = 9901;

long long pos[10000], cnt[10000];

long long power(long long a, long long b)
{
	int x = 1;
	while (b)
	{
		if (b % 2) x = (x * a) % p;
		a = (a * a) % p; 
		b /= 2;
	}
	return x;
}

long long calc(long long x, long long n)
{
	if (n == 0)
		return 1;
	if (n % 2 == 1)
		return (calc(x, n / 2) * (1 + power(x, n / 2 + 1))) % p;
	else
		return (calc(x, n / 2 - 1) * (1 + power(x, n / 2 + 1)) + power(x, n / 2)) % p;
}

int main()
{
	int A, B, n = 0;
	cin >> A >> B;
	int x = A;
	if (A <= 1)
	{
		cout << A << endl;
		return 0;
	}
	else if (B == 0)
	{
		cout << 1 << endl;
		return 0;
	}
	for (int i = 2; i <= int(sqrt(double(A))); i++)
	{
		bool flag = false;
		pos[n] = i;
		while (x % i == 0)
		{
			x /= i; cnt[n]++; flag = true;
		}
		if (flag) n++;
	}
	if (x > 1)
	{
		pos[n] = x; cnt[n] = 1; n++;
	}
	long long ans = 1;
	for (int i = 0; i < n; i++)
	{
		ans = (ans * calc(pos[i], cnt[i] * B)) % p;
	}
	cout << ans << endl;
}
这个代码比线筛还简洁一些- -

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值