poj1845

来源:互联网 发布:淘宝店铺类目怎么选 编辑:程序博客网 时间:2024/06/10 11:55

题目大意就是让你求A^B所得数的所有因子和%9901

这道题用到了数论的2个重要内容

1 任意一个合数都可以分解成若干个素数相乘的形式,把相同的素数写成立方的形式,就可以得到n=p1^a1*p2^a2...pn^an

2 一个数的因子直接求不好求,但是写出素数相乘的形式,变很简单。n的因子就是(1+p1+p1^2...p1^a1)*(1+p2...)*(1+p3...)

那么如何求等比式(1+p1+p1^2...p1^a1)?

对于n为奇数的情况 1+p+p^2+p^3可以写成(1+p^2)*(1+p)

那么推广一下得到(1+p+p^2+..p^(n/2))*(1+p^(n/2+1))

对于n为偶数的情况 1+p+p^2+p^3+p^4可以写成(1+p)*(1+p^3)+p^2的形式

那么推广一下得到(1+p+p^2+...p^(n/2-1))*(1+p^(n/2+1))

求每一个p^n快速幂一下就好了

下面是代码

//题意就是求A^B的所有因子的和模上9901,A和B的范围是0-5e7
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define mod 9901
const int MAXN=10000;
int prime[MAXN+1],isprime[MAXN+1];
int k=1;
void getPrime()//筛法求素数 
{
    for(int i=0;i<=MAXN;i++)
      isprime[i]=1;
    isprime[0]=isprime[1]=0;
    for(int i=2;i<=MAXN;i++)
    {
    if(isprime[i])
    {
    prime[k++]=i;
    for(int j=i*2;j<=MAXN;j+=i)
     isprime[j]=0;
}
}
}
long long factor[100][2];//存储一个数的素因子,factor[i][0]表示素因子,factor[i][1]表示该素因子有多少个
int factCnt=0;//表示有多少个不同的素因子 
void getFactor(int x)
{
int tmp=x;
for(int i=1;prime[i]<=tmp/prime[i];i++)
{
factor[factCnt][1]=0;
if(tmp%prime[i]==0)
{
factor[factCnt][0]=prime[i];
while(tmp%prime[i]==0)
  {
factor[factCnt][1]++;
tmp/=prime[i];
  }
  factCnt++;
}
}
if(tmp!=1)
   {
 factor[factCnt][0]=tmp;
 factor[factCnt++][1]=1;
   }

long long pow_m(int a,int n)//快速幂求a^n 
{
long long tem=a%mod;
long long ans=1;
while(n)
{
if(n&1)
{
ans*=tem;ans%=mod;
}
n>>=1;
tem*=tem;
tem%=mod;
}
return ans;
}
long long sum(int p,int n)//求解1+p+p^2+...p^n 
{
if(p==0)
 return 0;
if(n==0)
 return 1;
if(n&1)
 return ((1+pow_m(p,n/2+1))%mod*(sum(p,n/2)%mod))%mod;
else
 return ((1+pow_m(p,n/2+1))%mod*sum(p,n/2-1)+pow_m(p,n/2)%mod)%mod;
}
int main()
{
int n,m;
getPrime();    
while(~scanf("%d%d",&n,&m))
{
getFactor(n);
long long ans=1;
for(int i=0;i<factCnt;i++)
{
ans*=sum(factor[i][0],m*factor[i][1])%mod;
ans=ans%mod;
}
printf("%I64d\n",ans);
}

原创粉丝点击