首页 > 其他分享 >[NOI2016]循环之美

[NOI2016]循环之美

时间:2022-12-14 20:59:05浏览次数:55  
标签:prime map 10000001 int 之美 long NOI2016 循环 miu

链接:https://www.luogu.com.cn/problem/P1587 题目描述:求有多少个$\frac{a}{b}(1<=a<=n,1<=b<=m)$在$k$进制下是纯循环小数$(注意:相等的数只算一次)$。 题解:可以发现$\frac{a}{b}(1<=a<=n,1<=b<=m)$在$k$进制下是纯循环小数当且仅当$\frac{a}{b}$化为最简分数后分母与$k$互质。我们可以只在最简分数处算,则原问题化为求$\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)==1][gcd(j,k)==1]$ $\qquad\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)==1][gcd(j,k)==1]$ $=\sum_{i=1}^{n}\sum_{j=1}^{m}\sum_{d|gcd(i,j)}μ(d)[gcd(j,k)==1]$ $=\sum_{d=1}^{n}μ(d)\lfloor \frac{n}{d}\rfloor\sum_{d|j}[gcd(j,k)==1]$ $=\sum_{d=1}^{n}μ(d)\lfloor \frac{n}{d}\rfloor\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}[gcd(dj,k)==1]$ $=\sum_{d=1}^{n}μ(d)\lfloor \frac{n}{d}\rfloor [gcd(d,k)==1]\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}[gcd(j,k)==1]$ 令$f(n,k)=\sum_{i=1}^{n}[gcd(i,k)==1],g(n,k)=\sum_{i=1}^{n}μ(i)[gcd(i,k)==1]$ 则原式可以用数论分块快速求出,考虑如何快速求出这两个函数,可以利用递归的思想,将$k$推向$k/p$($p$为$k$的一个质因子)。 $f(n,k)=\sum_{i=1}^{n}[gcd(i,k)==1]$ $=\sum_{i=1}^{n}[gcd(i,\frac{k}{p})==1]-\sum_{i=1}^{n}[gcd(i,\frac{k}{p})==1][p|i]$ $=f(n,k/p)-\sum_{i=1}^{n}[gcd(i,\frac{k}{p})==1][p|i]$ $=f(n,k/p)-\sum_{i=1}^{\lfloor \frac{n}{p} \rfloor}[gcd(ip,\frac{k}{p})==1]$ 当$k$中含有两个质因子$p$时,该式就等于$f(n,k/p)$。 当$k$中含有一个质因子$p$时 原式$=f(n,k/p)-\sum_{i=1}^{\lfloor \frac{n}{p} \rfloor}[gcd(i,\frac{k}{p})==1]$ $=f(n,k/p)-f(\lfloor \frac{n}{p} \rfloor,k/p)$ $g(n,k)=\sum_{i=1}^{n}μ(i)[gcd(i,k)==1]$ $=\sum_{i=1}^{n}μ(i)[gcd(i,\frac{k}{p})==1]-\sum_{i=1}^{n}μ(i)[gcd(i,\frac{k}{p})==1][p|i]$ $=g(n,k/p)-\sum_{i=1}^{n}μ(i)[gcd(i,\frac{k}{p})==1][p|i]$ $=f(n,k/p)-\sum_{i=1}^{\lfloor \frac{n}{p} \rfloor}μ(ip)[gcd(ip,\frac{k}{p})==1]$ 当$k$中含有两个质因子$p$时,该式就等于$g(n,k/p)$。 当$k$中含有一个质因子$p$时 原式$=g(n,k/p)-\sum_{i=1}^{\lfloor \frac{n}{p} \rfloor}μ(i)μ(p)][gcd(i,p)==1][gcd(i,\frac{k}{p})==1]$ $=g(n,k/p)-μ(p)\sum_{i=1}^{\lfloor \frac{n}{p} \rfloor}μ(i)[gcd(i,k)==1]$ $=g(n,k/p)+\sum_{i=1}^{\lfloor \frac{n}{p} \rfloor}μ(i)[gcd(i,k)==1]$ $=g(n,k/p)+g(\lfloor \frac{n}{p} \rfloor,k)$ ``` #include #include #include #define N 10000000 using namespace std; int n,m,k,miu[10000001],prime[10000001],v[10000001],len; mapp; map<pair,long long>F; map<pair,long long>G; inline void prework() { miu[1]=1; for (int i=2;i<=N;++i) { if (!v[i]) { miu[i]=-1; v[i]=i; prime[++len]=i; } for (int j=1;j<=len;++j) { if (prime[j]*i>N||prime[j]>v[i]) break; v[i*prime[j]]=prime[j]; if (i%prime[j]==0) break; else miu[i*prime[j]]=-miu[i]; } } for (int i=2;i<=N;++i) miu[i]+=miu[i-1]; return; } inline long long sum_miu(register long long n) { if (n<=N) return miu[n]; if (p.find(n)!=p.end()) return p[n]; long long res=1,last; for (int i=2;i<=n;i=last+1) { last=n/(n/i); res-=(last-i+1)*sum_miu(n/i); } p.insert(make_pair(n,res)); return res; } inline long long f(register long long n,register int k) { if (F.find(make_pair(n,k))!=F.end()) return F[make_pair(n,k)]; if (k==1) return n; if ((k/v[k])%v[k]==0) return f(n,k/v[k]); register long long ans=f(n,k/v[k])-f(n/v[k],k/v[k]); F.insert(make_pair(make_pair(n,k),ans)); return ans; } inline long long g(register long long n,register int k) { if (G.find(make_pair(n,k))!=G.end()) return G[make_pair(n,k)]; if (n==0) return 0; if (k==1) return sum_miu(n); if ((k/v[k])%v[k]==0) return g(n,k/v[k]); register long long ans=g(n,k/v[k])+g(n/v[k],k); G.insert(make_pair(make_pair(n,k),ans)); return ans; } int main() { register long long ans=0,last; prework(); scanf("%d%d%d",&n,&m,&k); for (register int i=1;i<=min(n,m);i=last+1) { last=min(n/(n/i),m/(m/i)); ans+=(g(last,k)-g(i-1,k))*(n/i)*f(m/i,k); } printf("%lld\n",ans); return 0; }

标签:prime,map,10000001,int,之美,long,NOI2016,循环,miu
From: https://www.cnblogs.com/zhouhuanyi/p/16983489.html

相关文章