Codeforces 542D Superhero's Job 数论 哈希表 搜索
Posted zhouzhendong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 542D Superhero's Job 数论 哈希表 搜索相关的知识,希望对你有一定的参考价值。
原文链接https://www.cnblogs.com/zhouzhendong/p/CF542D.html
题目传送门 - CF542D
题目传送门 - 51Nod1477
题意
定义公式 $J(x) = sum_{1 leq k leq x 且 k|x 且 gcd (k,x/k) = 1} k$ 。
现在给定一个整数 $A$ ,要求有多少正整数 $x$ ,满足 $J(x)=A$ 。
$x|n$ 表示 $x$ 是 $n$ 的因子。
$gcd(a,b) 表示 $a$ 和 $b$ 的最大公约数。
$1leq Aleq 10^{12}$
题解
先考虑如何求 $J(x)$ 。
由于 $gcd(k,x/k)=1$ ,所以选出来的 $x$ 和 $x/k$ 的质因数集合没有交集。
故如果设 $x=prod p_i^{a_i}$ ,那么 $J(x) = prod (p_i^{a_i}+1)$ 。
于是我们考虑 dfs 枚举 A 的因数分解方式,加一些剪枝和优化就可以过了。
代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; LL read(){ LL x=0; char ch=getchar(); while (!isdigit(ch)) ch=getchar(); while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); return x; } const int N=1000005; LL n; struct hash_map{ static const int Ti=233,mod=1<<21; int cnt,nxt[mod+1],fst[mod+1]; LL k[mod+1],v[mod+1]; int Hash(LL x){ int v=x&(mod-1); return v==0?mod:v; } void clear(){ cnt=0; memset(fst,0,sizeof fst); } LL &operator [] (LL x){ int y=Hash(x); for (int p=fst[y];p;p=nxt[p]) if (k[p]==x) return v[p]; k[++cnt]=x,nxt[cnt]=fst[y],fst[y]=cnt; return v[cnt]=0; } }check,use; LL prime[N],pcnt,vis[N]; void get_prime(){ memset(vis,0,sizeof vis); pcnt=0; for (int i=2;i<N;i++){ if (vis[i]) continue; prime[++pcnt]=i; for (int j=i+i;j<N;j+=i) vis[j]=1; } } int Check(LL x){ if (x<=1) return 0; for (int i=1;prime[i]*prime[i]<=x&&i<=pcnt;i++) if (x%prime[i]==0){ while (x%prime[i]==0) x/=prime[i]; return x==1?prime[i]:0; } return x; } LL ans=0; LL fac[N*2],fc=0; void dfs(LL n,LL *d){ if (*d>n) return; if (check[n]&&!use[check[n]]) ans++; if (*d>=n/ *d) return; for (;*d<n/ *d;d++){ if (n%*d) continue; LL &v=use[check[*d]]; if (!v) v=1,dfs(n/ *d,d+1),v=0; } } int main(){ get_prime(); n=read(); if (n==1) return puts("1"),0; check.clear(); for (LL i=1;i*i<=n;i++){ if (n%i) continue; LL j=n/i; check[i]=Check(i-1); check[j]=Check(j-1); if (check[i]) fac[fc++]=i; if (i!=j&&check[j]) fac[fc++]=j; } use.clear(); sort(fac,fac+fc); fac[fc]=n+1; dfs(n,fac); printf("%lld",ans); return 0; }
以上是关于Codeforces 542D Superhero's Job 数论 哈希表 搜索的主要内容,如果未能解决你的问题,请参考以下文章
CodeCraft-19 and Codeforces Round #537 (Div. 2) A - Superhero Transformation
CodeCraft-19 and Codeforces Round #537 (Div. 2) B. Average Superhero Gang Power
CF w1d2 A. Superhero Transformation