题目大意:给你一个正整数
,为有多少非空序列
满足:
,且
中有不超过
个本质不同的质因子。
题解:
首先每个因数视为一个关于质因子的集合,这样一共有不超过
个集合。最朴素的dp是处理出这
种集合所有可能出现的序列,这样只能跑到c=5,跑不出c=6。
然后注意到可以继续优化,注意到每个质因子只会被最多两个集合覆盖,那么维护一个c位数,每位数0表示没有被覆盖,-1表示已经被覆盖两次了,否则表示其被哪个集合选中,然后最小表示一下这个c位数即可,实测只有三千多一点的状态。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define mod 1000000007
#define BAS 97ull
#define ull unsigned lint
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline lint inln() { lint x;scanf("%lld",&x);return x; }
const int MXST=3263+100,MXLEN=6+10,MXTRS=63+10;queue<int> q;
int TOT,dfslst[MXST][MXLEN],id[MXLEN];unordered_map<ull,int> hvm;
int sta[MXST][MXLEN],dp[MXST],d[MXST],val[MXTRS];vector<pii> g[MXST];
inline int add_edge(int u,int v,int w) { return g[u].pb(mp(v,w)),0; }
inline ull get_hv(int *a,int c)
{
ull res=0;
rep(i,1,c) res=res*BAS+a[i]+10;
return res;
}
inline int Trans(int *a,int *b,int v,int c)
{
int mx=0,las=0;rep(i,1,c) mx=max(mx,a[i]);
rep(i,1,c) if((v>>(i-1))&1)
{
if(a[i]==-1) return 0;
if(!a[i]) b[i]=mx+1;
else if(!las) b[i]=-1,las=a[i];
else if(las!=a[i]) return 0;
}
else b[i]=a[i];
rep(i,1,mx+1) id[i]=0;int cnt=0;
rep(i,1,c) if(b[i]>0)
{
if(!id[b[i]]) id[b[i]]=++cnt;
b[i]=id[b[i]];
}
return 1;
}
int Trstmp[MXLEN];
inline int getTrs(int *a,int v,int c)
{
if(!Trans(a,Trstmp,v,c)) return 0;
ull vl=get_hv(Trstmp,c);
if(!hvm.count(vl)) return 0;
return hvm[vl];
}
inline int Save(int *a,ull v,int c)
{
hvm[v]=++TOT;
// debug(TOT)sp<<": ";rep(i,1,c) cerr<<a[i]<<" ";cerr ln;
rep(i,1,c) sta[TOT][i]=a[i];
return 0;
}
int dfs(int x,int c,int all)
{
rep(i,1,all)
{
if(!Trans(dfslst[x],dfslst[x+1],i,c)) continue;
ull v=get_hv(dfslst[x+1],c);
if(!hvm.count(v))
Save(dfslst[x+1],v,c),dfs(x+1,c,all);
}
return 0;
}
inline int get_dp(int c,int all)
{
rep(i,1,TOT)
{
rep(j,1,all)
{
int k=getTrs(sta[i],j,c);if(!k) continue;
add_edge(i,k,val[j]),d[k]++;//,debug(i)sp,debug(j)sp,debug(k)ln;
}
}
while(!q.empty()) q.pop();
q.push(1),dp[1]=1;
while(!q.empty())
{
int x=q.front();q.pop();
Rep(i,g[x])
{
int y=g[x][i].fir;d[y]--;
if(!d[y]) q.push(y);
dp[y]=(dp[y]+(lint)g[x][i].sec*dp[x])%mod;
}
}
int ans=0;
rep(i,2,TOT) ans+=dp[i],(ans>=mod?ans-=mod:0);
return ans;
}
int pc[MXLEN];
int main()
{
lint n=inln();int c=0;
for(int i=2;(lint)i*i<=n;i++) if(n%i==0)
for(pc[++c]=1,n/=i;n%i==0;pc[c]++,n/=i);
if(n>1) pc[++c]=1;int all=(1<<c)-1;
rep(i,1,all)
{
val[i]=1;
rep(j,0,c-1) if((i>>j)&1) val[i]*=pc[j+1];
}
TOT=1;
dfs(0,c,all);
//debug(c)sp,debug(all)sp,debug(TOT)ln;
printf("%d\n",get_dp(c,all));
return 0;
}