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

    前面部分比较简单,就是无脑化式子,简单点讲好了。
    首先肯定在((x,y)=1)时才考虑这个分数,要求纯循环的话,不妨猜猜结论,就是y必须和K互质。所以答案是(sum_{i=1}^n sum_{j=1}^m [(i,j)=1] [(j,k)=1])

    然后用 ([(i,j)=1]=sum_{d|i,j} mu(d))大力化一化,很快就会得到:

    [sum_{d=1}^{min(n,m)} mu(d) frac{n}{d} sum_{d|j,jle m}[(j,k)=1] ]

    [=sum_{d=1}^{min(n,m)} mu(d) [(d,k)=1] frac{n}{d} sum_{j=1}^{frac{m}{d}}[(j,k)=1] ]

    令后面那一坨(sum_{j=1}^{frac{m}{d}}[(j,k)=1]=f(frac{m}{d})),它可以快速计算:

    [f(x)=sum_{j=1}^x [(j,K)=1] ]

    [=sum_{j=1}^x sum_{g|j,k} mu(g) ]

    [=sum_{g|k}mu(g) sum_{g|j} 1 ]

    [=sum_{g|k}mu(g) frac{x}{g} ]

    可以(O(sqrt k))计算。

    回到原式

    [sum_{d=1}^{min(n,m)} mu(d) [(d,k)=1] frac{n}{d} f(frac{m}{d}) ]

    这个显然可以分块吧,预处理一下(sum_{d=1}^{min(n,m)} mu(d)[(d,k)=1])的前缀和就可以(O(sqrt n *sqrt k))算答案了,因为是gcd的log,预处理做到2e7都不虚。
    然后就有84分了。

    考虑快速求(F(k,x)=sum_{d=1}^x mu(d)*[(d,k)==1]),同样拆后面的gcd。

    [F(k,x) =sum_{d=1}^x mu(d)*[(d,k)==1] ]

    [=sum_{d=1}^x mu(d) sum_{g|k,d} mu(g) ]

    [=sum_{g|k} mu(g) sum_{g|d} mu(d) ]

    [=sum_{g|k} mu(g) sum_{T=1}^{frac{x}{g}} mu(T*g) ]

    然后由于当((T,g) e 1)(mu(T*g))显然=0。

    [=sum_{g|k} mu(g) sum_{T=1}^{frac{x}{g}} [(T,g)==1]*mu(T)*mu(g) ]

    [=sum_{g|k} mu^2(g) sum_{T=1}^{frac{x}{g}} mu(T)*[(T,g)==1] ]

    [=sum_{g|k} mu^2(g) F(g,frac{x}{g}) ]

    然后递归算,顺便记忆化一下,另外当k=1时直接返回(sum_{i=1}^x mu(i)),因此要杜教筛预处理。

    (F(k,i))可以预处理一下(k=K)时x较小的若干项,会加快速度。

    我根本不会算这个的复杂度,想到这后就直接去写了,极限数据一下就跑出来了就交了,别问我复杂度是多少,我不知道。复杂度应该和杜教筛差不多吧(如果对g讨论一下在x的(sqrt x)段中的哪一段,这一段的k的约数统一计算的话)。

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #include<map>
    #define pl puts("lala")
    #define cp cerr<<"lala"<<endl
    #define fi first
    #define se second
    #define pb push_back
    #define ln putchar('
    ')
    using namespace std;
    inline int read()
    {
    	char ch=getchar();int g=1,re=0;
    	while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
    	while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+(ch^48),ch=getchar();
    	return re*g;
    }
    typedef long long ll;
    typedef pair<int,int> pii;
    
    inline int gcd(int a,int b)
    {
    	while(b) {int t=a%b; a=b; b=t;}
    	return a;
    }
    const int N=7e5+11;
    int prime[N],cnt=0,mu[N],smu[N],resf[N],K;
    bool isnotprime[N];
    void init()
    {
    	int n=N-11;
    	isnotprime[1]=1; mu[1]=1;
    	for(int i=2;i<=n;++i) 
    	{
    		if(!isnotprime[i]) prime[++cnt]=i,mu[i]=-1;
    		for(int j=1;j<=cnt&&i*prime[j]<=n;++j)
    		{
    			isnotprime[i*prime[j]]=1;
    			if(!(i%prime[j])) break;
    			mu[i*prime[j]]=-mu[i];
    		}
    	}
    	for(int i=1;i<=n;++i) smu[i]=smu[i-1]+mu[i];
    	for(int i=1;i<=n;++i) resf[i]=resf[i-1]+mu[i]*(gcd(i,K)==1);
    }
    
    map<int,int>mp;
    int M(int n)
    {
    	if(n<=N-11) return smu[n];
    	if(mp.count(n)) return mp[n];
    	int &ans=mp[n]; ans=1;
    	for(int i=2,j;i<=n;i=j+1)
    	{
    		j=n/(n/i);
    		ans-=M(n/i)*(j-i+1);
    	}
    	return ans;
    }
    
    map<int,int>F[2050];
    int calcF(int k,int x)
    {
    	if(k==1) return M(x);
    	if(k==K&&x<=N-11) return resf[x];
    	if(F[k].count(x)) return F[k][x];
    	int &ans=F[k][x];
    	for(int i=1;i*i<=k;++i) if(!(k%i))
    	{
    		if(mu[i]) ans+=mu[i]*mu[i]*calcF(i,x/i);
    		if(i*i!=k) 
    		{
    			int oth=k/i;
    			if(mu[oth]) ans+=mu[oth]*mu[oth]*calcF(oth,x/oth);
    		}
    	}
    	return ans;
    }
    
    int n,m;
    int divi[2050],tot=0;
    inline int f(int x)
    {
    	int ans=0;
    	for(int i=1;i<=tot;++i) ans+=mu[divi[i]]*(x/divi[i]);
    	return ans;
    }
    
    int main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("1.in","r",stdin);freopen("1.out","w",stdout);
    #endif
    	n=read(); m=read(); K=read();
    	init();
    	int mn=min(n,m);
    	M(mn);
    	for(int i=1;i*i<=K;++i) if(!(K%i))
    	{
    		divi[++tot]=i;
    		if(i*i!=K) divi[++tot]=K/i;
    	}
    	
    	ll ans=0;
    	for(int i=1,j;i<=mn;i=j+1)
    	{
    		j=min(n/(n/i),m/(m/i));
    		ans+=1ll*(n/i)*f(m/i)*(calcF(K,j)-calcF(K,i-1));
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    [古城子的房子] 贪心
    [小兔的棋盘] 组合数学
    [Triangle] Fibonacci+二分查找
    [Fibonacci] 矩阵快速幂
    [DP?]素数筛+Lucas定理+费马小定理
    react本地开发关闭eslint检查
    react 不同js文件里公用同一个变量
    js学习笔记
    node内存扩展,前端项目运行时报内存不足的错误
    Gitee码云通过WebHooks实现自动同步代码部署
  • 原文地址:https://www.cnblogs.com/thkkk/p/8982346.html
Copyright © 2011-2022 走看看