• 【GMOJ4496】互补约数


    题目

    题目链接:https://gmoj.net/senior/#main/show/4496

    [sum^{n}_{i=1}sum_{j|i}gcd(j,frac{i}{j}) ]

    (nleq 10^{11})

    思路

    [sum^{n}_{i=1}sum_{j|i}gcd(j,frac{i}{j}) ]

    [=sum^{n}_{i=1}sum^{lfloorfrac{n}{i} floor}_{j=1}gcd(i,j) ]

    枚举 (gcd=d)

    [sum^{n}_{d=1}dsum^{lfloorfrac{n}{d^2} floor}_{i=1}sum^{lfloorfrac{n}{d^2i} floor}_{j=1}[gcd(i,j)=1] ]

    (g(n)=sum^{n}_{i=1}sum^{lfloorfrac{n}{i} floor}_{j=1}[gcd(i,j)=1]),则原式 (=sum^{n}_{d=1}g(lfloorfrac{n}{d^2} floor))

    [g(n)=sum^{sqrt{n}}_{d=1}mu(d)sum^{lfloorfrac{n}{d^2} floor}_{i=1}lfloorfrac{n}{d^2i} floor ]

    整除分块即可。记忆化一下可以卡进 (1s)

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int N=350010,M=10000000;
    int m,prm[N],mu[N];
    bool v[N];
    ll n,ans,f[M];
    
    void findprm(int n)
    {
    	mu[1]=1;
    	for (int i=2;i<=n;i++)
    	{
    		if (!v[i]) prm[++m]=i,mu[i]=-1;
    		for (int j=1;j<=m;j++)
    		{
    			if (i>n/prm[j]) break;
    			v[i*prm[j]]=1; mu[i*prm[j]]=-mu[i];
    			if (!(i%prm[j])) { mu[i*prm[j]]=0; break; }
    		}
    	}
    }
    
    ll calc2(ll n)
    {
    	if (n<M && f[n]) return f[n];
    	ll res=0;
    	for (ll l=1,r;l<=n;l=r+1)
    	{
    		r=n/(n/l);
    		res+=(r-l+1)*(n/l);
    	}
    	if (n<M) f[n]=res;
    	return res;
    }
    
    ll calc1(ll n)
    {
    	ll res=0;
    	for (ll i=1;i*i<=n;i++)
    		res+=mu[i]*calc2(n/i/i);
    	return res;
    }
    
    int main()
    {
    	freopen("gcd.in","r",stdin);
    	freopen("gcd.out","w",stdout);
    	findprm(N-1);
    	scanf("%lld",&n);
    	for (ll i=1;i*i<=n;i++)
    		ans+=i*calc1(n/i/i);
    	cout<<ans;
    	return 0;
    }
    
  • 相关阅读:
    tcp/ip--百度百科
    Web service--百度百科
    .NET--百度百科
    ibatis--百度百科
    Struts2--百度百科
    spring--百度百科
    从头认识Spring-1.15 对SpEl的值的操作(1)-数值运算
    performSelector 方法的自己主动俘获特性
    图解WinHex使用入门
    LINQ使用与并行
  • 原文地址:https://www.cnblogs.com/stoorz/p/15006209.html
Copyright © 2020-2023  润新知