【CF542D】Superhero's Job 暴力
阿新 • • 發佈:2018-04-02
redo names family ++ lag bre 所有 red size
【CF542D】Superhero‘s Job
題意:$ f(x)=\sum\limits_{d|x,gcd(d,{x\over d})=1} d$
給出 $A$ ,求方程 $f(x)=A$ 的正整數解的個數。
$1\le A\le 10^{12}$
題解:首先我們發現f這個函數是積性的,$f(p^a)=1+p^a$(p是質數)。所以我們枚舉$A$的所有約數,看一下他能不能拆成$1+p^a$的形式,並把p相同的放到一起。設f[i]表示乘積為i的方案數,暴力DP即可。你甚至可以用map。
附:$10^{12}$以內約數最多的數為
#include <cstring> #include <iostream> #include <cstdio> #include <map> #include <algorithm> #include <cmath> using namespace std; typedef long long ll; const int N=1000000; ll n; int num,m,cnt,tot,tim; int ep[100]; int pri[N>>1],np[N+10],f[2][10000]; ll v[10000],pr[100]; struct node { int bel; ll val; }p[10000]; map<ll,int> ref,vis; void dfs(int x,ll now) { if(x==m+1) { v[++tot]=now,ref[now]=tot; return ; } for(int i=0;i<=ep[x];i++) dfs(x+1,now),now*=pr[x]; } bool cmp(const node &a,const node &b) { return (a.bel==b.bel)?(a.val<b.val):(a.bel<b.bel); } int main() { scanf("%lld",&n); int i,j,d=0; ll tn=sqrt(n); for(i=2;i<=tn;i++) { if(!np[i]) pri[++num]=i; for(j=1;j<=num&&i*pri[j]<=tn;j++) { np[i*pri[j]]=1; if(i%pri[j]==0) break; } } ll t=n; for(i=1;i<=num&&pri[i]*pri[i]<=t;i++) if(t%pri[i]==0) { pr[++m]=pri[i]; while(t%pri[i]==0) t/=pri[i],ep[m]++; } if(t!=1) pr[++m]=t,ep[m]=1; dfs(1,1); for(i=2;i<=tot;i++) if(v[i]!=2) { t=v[i]-1; int flag=1; for(j=1;j<=num&&pri[j]*pri[j]<=t;j++) if(t%pri[j]==0) { t/=pri[j]; while(t%pri[j]==0) t/=pri[j]; if(t!=1) flag=0; else t=pri[j]; break; } if(flag) { p[++cnt].val=v[i]; if(!vis[t]) vis[t]=++tim; p[cnt].bel=vis[t]; } } sort(p+1,p+cnt+1,cmp); f[0][1]=1; for(j=1;j<=cnt;j++) { if(p[j].bel!=p[j-1].bel) d^=1,memcpy(f[d],f[d^1],sizeof(f[0][0])*(tot+1)); for(i=1;i<=tot;i++) if(v[i]%p[j].val==0) f[d][i]+=f[d^1][ref[v[i]/p[j].val]]; } printf("%d",f[d][tot]); return 0; }
【CF542D】Superhero's Job 暴力