P4714 「数学」约数个数和

题目求的东西可以转化为:

给你一个数,每次把它变成它的一个约数,重复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;
}
posted @ 2019-03-31 18:46  Creed-qwq  阅读(201)  评论(0编辑  收藏  举报