4 条题解
-
0
注意到 给出了质因数分解形式
不难看出,所有满足条件的 ,一定对于所有的 满足
所以我们就可以对于每一个 ,求出满足的最小的 ,记为 ,那么答案就是
可以用类似于倍增的方式求,先预处理出 表示一个质数 在的唯一分解中的指数,递推式为 ,之后就可以对于每个 从大到小遍历 ,如果存在正整数 使得 那么便让 减去 ,并让答案加上 ,(其实就是把 拆成 进制,再利用阶乘的性质得出 的唯一分解中 上面的指数,只不过这里是反过来构造 )。
下面是代码,复杂度不会证(,但跑的很快。
#include<bits/stdc++.h> using namespace std; const long long maxxxxx=1000000000000000000ll; bool b[609]; int p[109],len=0,cnt[109]; long long a[109],st[109][71],fac[109][71]; int main(){ b[1]=1; for(int i=2;len<100;i++){ if(!b[i]) p[++len]=i; for(int j=1;i*p[j]<=550&&j<=len;j++){ b[i*p[j]]=1; if(i%p[j]==0) break; } } for(int i=1;i<=100;i++) while(st[i][cnt[i]]<=maxxxxx){ if(st[i][cnt[i]]>(maxxxxx-1)/p[i]) break; ++cnt[i]; st[i][cnt[i]]=st[i][cnt[i]-1]*p[i]+1; } for(int i=1;i<=100;i++){ fac[i][0]=1; for(int j=1;j<=cnt[i];j++) fac[i][j]=fac[i][j-1]*p[i]; } int T; scanf("%d",&T); while(T--){ int k; long long sna=1; scanf("%d",&k); for(int i=1;i<=k;i++) scanf("%lld",&a[i]); for(int i=1;i<=k;i++){ if(a[i]==0) continue; long long x=a[i],ans=0; int l=0,r=cnt[i]; while(l+1<r){ int mid=(l+r)>>1; if(st[i][mid]<=x) l=mid; else r=mid; } long long ffac=fac[i][l]; for(int j=l;j>=1;j--){ if(x>=st[i][j]){ long long y=x/st[i][j]; x-=y*st[i][j]; ans+=y*ffac; } ffac/=p[i]; } sna=max(sna,ans); } printf("%lld\n",sna); } return 0; }
信息
- ID
- 737
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 9
- 标签
- (无)
- 递交数
- 53
- 已通过
- 4
- 上传者