标签:lld print clu 分解质因数 中间 get pre ret 注意
题目求的东西可以转化为:
给你一个数,每次把它变成它的一个约数,重复k次,求方案数。(中间过程有一步不同则视为不同)
这个东西显然可以dp,但是n,k<=1e18。
考虑每个质因子分别算,就又转化为一个新的问题,给你一个数,每次可以把它变成一个<=它的数字,重复k次。求方案数。(中间过程有一步不同则视为不同)
这个可以直接插板法来算。设x=π pi^ti,则ans=πC(ti+1+k-1,ti)。
这里的组合数,虽然n是1e18级别的,但m的取值<=60,可以直接组合数横向递推来求。
然而我又自闭了,写了一个矩阵乘法优化dp来算qwq。
最后注意对n分解质因数要用pollard_rho。
#include<bits/stdc++.h>
#define M 70
#define N 110000
#define eps 1e-7
#define inf 1e9+7
#define db double
#define ll long long
#define ldb long double
using namespace std;
inline ll read()
{
char ch=0;
ll x=0,flag=1;
while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*flag;
}
const ll mo=998244353;
ll rd(ll p){return rand()%p*rand()%p*rand()%p*rand()%p;}
ll ksc(ll x,ll y,ll p){return ((x*y-(ll)(((ldb)x*y+0.5)/p)*p)%p+p)%p;}
ll ksm(ll x,ll k,ll p){ll ans=1;while(k){if(k&1)ans=ksc(ans,x,p);k>>=1;x=ksc(x,x,p);}return ans;}
ll prime[N]={0,2,3,5,7,11,13,17,19,23};
bool miller_rabin(ll p)
{
if(p<=1)return false;
ll k=0,t=p-1;while(!(t&1))t>>=1,k++;
for(ll i=1;i<=9;i++)
{
if(p==prime[i])return true;
if(p%prime[i]==0)return false;
}
for(ll i=1;i<=9;i++)
{
ll x=ksm(prime[i],t,p),last;
for(ll j=1;j<=k;j++)
{
last=x;x=ksc(x,x,p);
if(x==1&&(last!=1&&last!=p-1))
return false;
}
if(x!=1)return false;
}
return true;
}
set<ll>S;
set<ll>::iterator it;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll find(ll n)
{
ll k=2,x=rd(n-1)+1,y=x,d=1,c=rd(n-1)+1;
for(ll i=1;d==1;i++)
{
x=(ksc(x,x,n)+c)%n;
d=gcd(abs(x-y),n);
if(i==k)k<<=1,y=x;
}
return d;
}
void pollard_rho(ll n)
{
if(n==1)return;
if(miller_rabin(n))return (void)S.insert(n);
ll t=n;
while(t==n)t=find(n);
pollard_rho(t);pollard_rho(n/t);
}
ll size;
struct matrix
{
ll s[M][M];
void clear(){memset(s,0,sizeof(s));}
}f,g;
matrix operator*(matrix a,matrix b)
{
matrix ans;ans.clear();
for(ll i=0;i<=size;i++)for(ll j=0;j<=size;j++)for(ll k=0;k<=size;k++)
ans.s[i][j]=(ans.s[i][j]+(1ll*a.s[i][k]*b.s[k][j]%mo))%mo;
return ans;
}
matrix E()
{
matrix ans;ans.clear();
for(ll i=0;i<=size;i++)ans.s[i][i]=1;
return ans;
}
matrix pow(matrix x,ll k)
{
matrix ans=E();
while(k)
{
if(k&1)ans=ans*x;
k>>=1;x=x*x;
}
return ans;
}
int main()
{
srand(time(0));
ll n=read(),k=read()+1,ans=1;pollard_rho(n);
for(it=S.begin();it!=S.end();it++)
{
ll x=n,o=*it;size=0;
while(x%o==0)x/=o,size++;
f.clear();f.s[0][size]=1;g.clear();
for(ll i=0;i<=size;i++)for(ll j=0;j<=i;j++)g.s[i][j]=1;
f=f*pow(g,k);
ll t=0;
for(ll i=0;i<=size;i++)t=(t+f.s[0][i])%mo;
ans=1ll*ans*t%mo;
}
printf("%lld",ans);
return 0;
}
标签:lld print clu 分解质因数 中间 get pre ret 注意
原文地址:https://www.cnblogs.com/Creed-qwq/p/10632519.html