题目:
分析:
啊,范围是(1e24),出题人身体健康冚家富贵嗷
不敢用__int128,手写高精度(
考虑(N=prod_{i=1}^{m}p_i^{k_i})
不难发现最后的答案只与(k)有关,尝试期望(dp)
前缀和优化一下
状态(K)由状态(K')转来,(K)和(K')只有一位差距1
我们暴力搜索最大的状态,明显是由最小的质数构成,且(N)最多只会有20个质因数
两个状态如果排序后相同,这两个状态的值就会相同(每一位等价)
直接将搜索出来的状态哈希或者直接加入map查询
然后就暴力预处理所有状态了
复杂度玄学,不过爆搜出的状态数级别是(1e5),预处理卡着时间过(
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<iostream>
#include<map>
#include<bitset>
#include<string>
#define maxn 200005
#define K 20
#define MOD 1000000007
#define maxm 105
using namespace std;
const long long D=1000000ll*1000000ll;
inline long long getint()
{
long long num=0,flag=1;char c;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
return num*flag;
}
map<int,int>M;
int ans[maxn],sum[maxn][21];
int cnt,tot,pri[maxm],f[maxm];
char s[maxm];
inline bool cmp(int x,int y){return x>y;}
inline int upd(int x){return x<MOD?x:x-MOD;}
struct BIGNUM{
long long p[2];
inline void getnum(long long x)
{p[0]=p[1]=0,p[0]=x/D,p[1]=x%D;}
friend BIGNUM operator *(BIGNUM x,long long y)
{
x.p[0]*=y,x.p[1]*=y,x.p[0]+=x.p[1]/D,x.p[1]%=D;
return x;
}
friend bool operator <(BIGNUM x,BIGNUM y)
{
return x.p[0]==y.p[0]?x.p[1]<y.p[1]:x.p[0]<y.p[0];
}
friend bool operator <=(BIGNUM x,BIGNUM y)
{
return x.p[0]==y.p[0]?x.p[1]<=y.p[1]:x.p[0]<y.p[0];
}
friend BIGNUM operator /(BIGNUM x,long long y)
{
x.p[1]+=x.p[0]%y*D,x.p[0]/=y,x.p[1]/=y;
return x;
}
friend long long operator %(BIGNUM x,long long y)
{
x.p[1]+=x.p[0]%y*D;
return x.p[1]%y;
}
}N;
pair<BIGNUM,vector<int> >p[maxn];
vector<int>d;
inline int ksm(int num,int k)
{
int ret=1;
for(;k;k>>=1,num=1ll*num*num%MOD)if(k&1)ret=1ll*ret*num%MOD;
return ret;
}
inline int solve(vector<int>a,int p)
{
while(p<K&&a[p]<a[p+1])swap(a[p],a[p+1]),p++;
int ans=0;
for(int i=0,sz=a.size();i<sz;i++)ans=ans*MOD+a[i];
return M[ans];
}
inline int getans(vector<int>a)
{
sort(a.begin()+1,a.end(),cmp);
int ans=0;
for(int i=0,sz=a.size();i<sz;i++)ans=ans*MOD+a[i];
return M[ans];
}
inline void init()
{
for(int i=2;i<=100;i++)
{
if(!f[i])pri[++tot]=f[i]=i;
for(int j=1;j<=tot&&pri[j]<=f[i];j++)
{
int tmp=pri[j]*i;
if(tmp>100)break;
f[tmp]=pri[j];
}
}
}
inline void work(BIGNUM now,int pos,int x)
{
p[++cnt]=make_pair(now,d);
for(int i=1;i<=x&&now*pri[pos]<=N;i++)
now=now*pri[pos],d[pos]=i,work(now,pos+1,i),d[pos]=0;
}
int main()
{
init(),N.getnum(1);
for(int i=1;i<=24;i++)N=N*10;
d.resize(K);
BIGNUM num;num.getnum(1);
work(num,1,100);
sort(p+1,p+cnt+1);
for(int i=1;i<=cnt;i++)
{
long long val=0;
for(int j=0,sz=p[i].second.size();j<sz;j++)val=val*MOD+p[i].second[j];
M[val]=i;
}
ans[1]=0;
for(int i=0;i<=K;i++)sum[1][i]=0;
for(int i=2;i<=cnt;i++)
{
for(int j=K-1;j>=0;j--)
{
sum[i][j]=sum[i][j+1];
if(p[i].second[j])
{
vector<int>tmp=p[i].second;tmp[j]--;
sum[i][j]=upd(sum[i][j]+sum[solve(tmp,j)][j]);
}
}
int tmp=1;
for(int j=0,sz=p[i].second.size();j<sz;j++)tmp=1ll*tmp*(p[i].second[j]+1)%MOD;
ans[i]=1ll*(sum[i][0]+tmp)*ksm(tmp-1,MOD-2)%MOD;
for(int j=0;j<=K;j++)sum[i][j]=upd(sum[i][j]+ans[i]);
}
BIGNUM n;
while(~scanf("%s",s))
{
int tmp=strlen(s);
for(int i=tmp-1;~i;i--)s[25-tmp+i]=s[i];
for(int i=0;i<25-tmp;i++)s[i]='0';
long long pw=D/10;
n.getnum(0);
for(int i=13;i<25;i++)n.p[1]+=1ll*pw*(s[i]-48),pw/=10;
pw=D;
for(int i=0;i<13;i++)n.p[0]+=1ll*pw*(s[i]-48),pw/=10;
int m=getint();
vector<int>a;
a.resize(1);
for(int i=1;i<=m;i++)
{
int x=getint(),cnt=0;
while(n%x==0)cnt++,n=n/x;
a.push_back(cnt);
}
a.resize(K);
printf("%d
",ans[getans(a)]);
}
}