Sumdiv 二分
Posted 偶尔爆零的蒟蒻
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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).
题意
求
a
b
a^b
ab的所有因子之和对
9901
9901
9901取模
题干很短,没想到背后原理一大堆。
感受到了数论的强大
定理参考
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<stack>
#include<iomanip>
using namespace std;
#define ff first
#define ss second
#define ms(a,x) memset(a,x,sizeof(a))
#define rush() int T;scanf("%d",&T);while(T--)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
#define inf 0x3f3f3f3f //10 6110 9567<2^30=10 7374 1824
#define iinf 0x7fffffff //
const double eps=1e-6;
const int mod=9901;
const int MAX=1e5;
//快速幂取模
int power(int a,int b){
int res=1;
a%=mod;
while(b){
if(b&1)res=(res*a)%mod;
b>>=1;
a=(a*a)%mod;
}
return res;
}
int p[MAX+5];//素数数组
int cnt;
//欧拉筛
//原理:每个合数都存在一个最小质因子
void getPrime(){
for(int i=2;i<=MAX;i++){
if(!p[i])p[++cnt]=i;
// 用之前产生的素数判断,逐渐扩展
// 以最小质因子将合数划分
for(int j=1;j<=cnt&&i*p[j]<=MAX;j++){
p[i*p[j]]=1;
if(i%p[j]==0)break;//最小质因子分解的界限
//如果不中断,则i*p[j+1]被p[j+1]分解
//设i=p[j]*k,表示i被最小质因子p[j]分解
//i*p[j+1]=p[j]*k*p[j+1]
//p[j+1]>p[j]
//即用p[j+1]分解不是最小的质因子
//会造成之后某个数重复判断,产生不必要的运算
}
}
}
//A=pi^ki*...*pj^kj 正整数A可被唯一分解为若干素数乘积,p为素数
//S(A)=(1+pi+...+pi^ki...)*...*(1+pj+...pj^kj...) A的所有因子和
//A^B=pi^(ki*B)*...*pj^(kj*B)
//S(A^B)=(1+pi+pi^2...+pi^(ki*B))*...*(1+pj+pj^2+...+pj^(kj*B))
//si(A^B)=1+pi+pi^2+...+pi^(ki*B) 取其一部分
//n为偶数 (1+p+...+p^(n/2-1))*(1+p^(n/2+1))+p^(n/2)
//n为奇数 (1+p+...+p^(n/2))*(1+p^(n/2+1)) n/2会造成下取整 n/2+n/2+1=n
//求解因子和递推式的值
int sum(int p,int n){
if(n==0)return 1;
if(n&1) return (sum(p,n>>1)%mod*(1+power(p,(n>>1)+1)%mod))%mod;
else return (sum(p,(n>>1)-1)*(1+power(p,(n>>1)+1))%mod+power(p,n>>1)%mod)%mod;
}
int main(){
getPrime();
int a,b;
cin>>a>>b;
int ans=1;
//提取小于自身的因子,以及幂次
for(int i=1;p[i]*p[i]<=a;i++){
if(a%p[i]==0){
int c=0;
while(a%p[i]==0){
c++;
a/=p[i];
}
ans=(ans*sum(p[i],b*c))%mod;
}
}
//剩下的a是质数
if(a>1){
ans=(ans*sum(a,b))%mod;
}
cout<<ans<<endl;
}
以上是关于Sumdiv 二分的主要内容,如果未能解决你的问题,请参考以下文章