Summer Training day4 Sumdiv

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). 


下面有两种办法求,一种是使用逆元的方法,把除以(p-1)变成×p-1的逆元。但这样是不行的,因为p-1不一定有逆元

第二种方法是把上面的东西转换成多项式相乘的形式,然后用类似于快速幂的分治策略解决

代码:

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long LL;
LL A,B;
LL MOD = 9901;
LL mod_pow(LL x,LL p,LL mod)
{
       LL ans = 1;
       while(p > 0)
       {
              if(p & 1)
                     ans = (x * ans)%mod;
              x = (x*x) % mod;
              p >>= 1;
       }
       return (ans + mod )% mod;
}

LL mod_inverse_feima(LL a,LL m)
{
       LL ans = mod_pow(a,m-2,m);
       return (ans%m+m);
}
int prime[1000];
int prime_cnt[1000];
int cnt = 0;

LL solve(LL x,LL step){
	if(step == 0) return 0;
	if(step == 1) return 1; 
	if(step == 2){
		return (x + 1)%MOD; 
	}
	if(step%2 == 0){
		return (mod_pow(x,step/2,MOD)+1)*solve(x,step/2)%MOD;
	}
	else{
		return solve(x,step-1) + mod_pow(x,step-1,MOD)%MOD; 
	}
}

void solve2(){
	cnt = 0;
	LL num = A;
	for(int i = 2;i * i <= A;i++){
		if(num % i == 0){
			prime[cnt] = i;
			int e = 0;
			while(num % i == 0){
				num /= i;
				e++;
			}
			prime_cnt[cnt] = e;
			cnt++;
		}
	}
	if(num > 1){
		prime[cnt] = num;
		prime_cnt[cnt++] = 1;
	}
	LL ans = 1;
	for(int i = 0;i < cnt;i++){
		LL tmp = 0;
		tmp = (solve(prime[i],prime_cnt[i] * B + 1))  % MOD;
		ans = ans * tmp % MOD;
	}
	printf("%lld\n",ans);
}


int main(){
	while(cin>>A>>B){
		solve2();
	}
	
	return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是用C++实现上述思路的代码: ```cpp #include <iostream> #include <vector> using namespace std; const int mod = 1000000007; // 线性筛法计算欧拉函数的前缀和 void calculatePhi(vector<int>& phi, vector<int>& prime, vector<bool>& isPrime, int k) { phi[1] = 1; for (int i = 2; i <= k; i++) { if (isPrime[i]) { prime.push_back(i); phi[i] = i - 1; } for (int j = 0; j < prime.size() && i * prime[j] <= k; j++) { isPrime[i * prime[j]] = false; if (i % prime[j] == 0) { phi[i * prime[j]] = phi[i] * prime[j]; break; } else { phi[i * prime[j]] = phi[i] * (prime[j] - 1); } } } // 计算前缀和 for (int i = 2; i <= k; i++) { phi[i] = (phi[i] + phi[i - 1]) % mod; } } // 计算⌊n/i⌋的前缀和 vector<int> calculateDivPrefixSum(int n, int k) { vector<int> sumDiv(k + 1, 0); for (int i = 1; i <= k; i++) { sumDiv[i] = (sumDiv[i - 1] + n / i) % mod; } return sumDiv; } int main() { int k; cin >> k; vector<int> phi(k + 1, 0); vector<int> prime; vector<bool> isPrime(k + 1, true); calculatePhi(phi, prime, isPrime, k); vector<int> sumDiv = calculateDivPrefixSum(k, k); int result = 0; for (int i = 1; i <= k; i++) { int factorCount = k / i; int temp = (sumDiv[factorCount] - sumDiv[i - 1] + mod) % mod; result = (result + phi[i] * temp) % mod; } cout << result << endl; return 0; } ``` 你可以将上述代码保存为一个.cpp文件,然后使用C++编译器进行编译和运行。输入k的值,即可得到最终结果。 希望对你有帮助!如果还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值