版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/V5ZSQ/article/details/83584478
Description
正面临算设课程的考试。
设
对于给定的 (其中 为质数),求 中质因子 的出现次数,即求一个最大的非负整数 满足 整除 。
由于是算设课的考试,答案当然是对 取模的。
Input
一行,两个正整数 ,其中 是质数
Output
一行,一个整数,质因子 的出现次数,答案对 取模。
Sample Input
233 2333
Sample Output
861127073
Solution
记所给素数为 , 表示 中素数 的幂指数,那么有
考虑
,答案即为
,而
其中
故有
,用矩阵快速幂维护
的值即可,时间复杂度
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=100001;
#define mod 1000000007
int add(int x,int y)
{
x+=y;
if(x>=mod)x-=mod;
return x;
}
int mul(int x,int y)
{
ll z=1ll*x*y;
return z-z/mod*mod;
}
int Pow(int x,int y)
{
ll z=1;
while(y)
{
if(y&1)z=mul(z,x);
x=mul(x,x);
y>>=1;
}
return z;
}
typedef int M[3][3];
void MUL(M &A,M B)
{
M C;
memset(C,0,sizeof(C));
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
for(int k=0;k<3;k++)
C[i][j]=add(C[i][j],mul(A[i][k],B[k][j]));
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
A[i][j]=C[i][j];
}
void POW(M &A,int n)
{
M B;
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
B[i][j]=(i==j);
while(n)
{
if(n&1)MUL(B,A);
MUL(A,A);
n>>=1;
}
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
A[i][j]=B[i][j];
}
int main()
{
int p,m;
M A;
while(~scanf("%d%d",&p,&m))
{
A[0][0]=p,A[0][1]=(mod+1)/2,A[0][2]=mod-(mod+1)/2;
A[1][0]=0,A[1][1]=mul(p,p),A[1][2]=0;
A[2][0]=0,A[2][1]=0,A[2][2]=p;
POW(A,m);
int ans=add(mul(A[0][1],p),mul(A[0][2],p));
ans=add(ans,mul(add(Pow(p,m),mod-1),Pow(p-1,mod-2)));
printf("%d\n",ans);
}
return 0;
}