zoukankan      html  css  js  c++  java
  • NOI2016 循环之美

    题目传送门

    分析:
    反正都是看博客写的,直接上链接,写得很好
    OrzOrzOrz

    这题可以用来复习一下杜教筛
    列两个公式记一下:

    (F(n)=sum_{i=1}^{n}mu(i)=1-sum_{i=2}^{n}F(lfloorfrac{n}{i} floor))
    (G(n)=sum_{i=1}^{n}varphi(i)=frac{n(n+1)}{2}-sum_{i=2}^{n}G(lfloorfrac{n}{i} floor))
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<queue>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<ctime>
    #include<set>
    
    #define maxn 200005
    
    using namespace std;
    
    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;
    }
    
    int n,m,K;
    long long pri[maxn],mu[maxn],cnt;
    int np[maxn],prik[maxn],cntk;
    long long f[2005],ans;
    map<long long,long long>Mu;
    map<long long,long long>G[11];
    
    inline int gcd(int p,int q)
    {return q?gcd(q,p%q):p;}
    inline void init()
    {
    	mu[1]=1;
    	for(int i=2;i<maxn;i++)
    	{
    		if(!np[i])pri[++cnt]=i,mu[i]=-1;
    		for(int j=1;j<=cnt&&i*pri[j]<maxn;j++)
    		{
    			np[i*pri[j]]=1;
    			if(i%pri[j]==0)break;
    			mu[i*pri[j]]=-mu[i];
    		}
    	}
    	for(int i=1;i<maxn;i++)mu[i]+=mu[i-1];
    	for(int i=1;i<=K;i++)f[i]=f[i-1]+(gcd(i,K)==1);
    }
    
    inline long long getf(int x){return (x/K)*f[K]+f[x%K];}
    inline long long getmu(int x)
    {
    	if(x<maxn)return mu[x];
    	if(Mu.count(x))return Mu[x];
    	long long tmp=1;
    	for(int i=2,j;i<=x;i=j+1)
    		j=x/(x/i),tmp-=getmu(x/i)*(j-i+1);
    	return Mu[x]=tmp;
    }
    inline long long getg(int x,int y)
    {
    	if(!x)return getmu(y);
    	if(y<=1)return y;
    	if(G[x].count(y))return G[x][y];
    	return G[x][y]=getg(x-1,y)+getg(x,y/prik[x]);
    }
    
    int main()
    {
    	n=getint(),m=getint(),K=getint();
    	init();
    	for(int i=1;i<=cnt&&pri[i]<=K;i++)if(K%pri[i]==0)prik[++cntk]=pri[i];
    	for(int i=1,j;i<=min(n,m);i=j+1)
    	{
    		j=min(n/(n/i),m/(m/i));
    		ans+=(getg(cntk,j)-getg(cntk,i-1))*(n/i)*getf(m/i);
    	}
    	printf("%lld
    ",ans);
    }
    

  • 相关阅读:
    [LeetCode] 1218. Longest Arithmetic Subsequence of Given Difference 最长定差子序列
    [LeetCode] 1217. Minimum Cost to Move Chips to The Same Position 玩筹码
    [LeetCode] 1209. Remove All Adjacent Duplicates in String II 移除字符串中所有相邻的重复字符之二
    [.Net Core] Visual Studio for Mac Add Client Side Library
    一手遮天 Android
    一手遮天 Android
    一手遮天 Android
    一手遮天 Android
    一手遮天 Android
    一手遮天 Android
  • 原文地址:https://www.cnblogs.com/Darknesses/p/12986518.html
Copyright © 2011-2022 走看看