• [HDU5942]Just a Math Problem(莫比乌斯反演)


    题面

    http://acm.hdu.edu.cn/showproblem.php?pid=5942

    题解

    前置知识

    引理

    [2^{f(n)}={sumlimits_{d1*d2=n}[(d1,d2)=1]} ]

    • 此处的f(n)即为题目中的f(n)。

    证明:设(n={prod_{i=1}^{k}}{p_i^{alpha_i}}),各(p_i)是质数。

    [RHS = {prodlimits_{i=1}^{k}}{sumlimits_{eta_1+eta_2=alpha_i}}[min(eta_1,eta_2)=0] ]

    [={prodlimits_{i=1}^{k}}2=2^k=LHS ]

    引理得证。

    回原题

    [{sumlimits_{i=1}^{n}}2^{f(i)} ]

    [={sumlimits_{i=1}^{n}}{sumlimits_{d1*d2=i}}[(d1,d2)=1] ]

    [={sumlimits_{d1*d2{leq}n}}[(d1,d2)=1] ]

    [={sumlimits_{d1*d2{leq}n}}{ }{sumlimits_{d|(d1,d2)}}{mu(d)} ]

    [={sumlimits_{d}}{mu(d)}{sumlimits_{d1*d2{leq}n}}[d|d1][d|d2] ]

    [={sumlimits_{d}}{mu(d)}*s({lfloor}{frac{n}{d^2}}{ floor}) ]

    [={sumlimits_{d{leq}{sqrt{n}}}}{mu(d)}*s({lfloor}{frac{n}{d^2}}{ floor}) ]

    其中s(n)表示({sum_{i=1}^{n}}{lfloor}{frac{n}{i}}{ floor})。求s(n)是经典的数论分块问题,可以(O(sqrt{n}))解决。

    总时间复杂度(O(T({sqrt{frac{n}{1^2}}}+{sqrt{frac{n}{2^2}}}+…+{sqrt{frac{n}{{sqrt{n}}^2}}})))

    [=O(T{sqrt{n}}H({sqrt{n}}))$$(H为调和级数) $$=O(T{sqrt{n}}logn)]

    • P.S.此题巨卡无比;需要各种卡常技巧;比如给s加一些记忆化,mu=0时跳过s的计算,以及尽一切可能避免mod等等。

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define sqrtN 1000000
    #define rg register
    #define ll long long
    #define mod 1000000007
    
    const ll T = 20000000;
    
    namespace ModCalc{
    	inline void Inc(ll &x,ll y){
    		x += y;if(x >= mod)x -= mod;
    	}
    	
    	inline void Dec(ll &x,ll y){
    		x -= y;if(x < mod)x += mod;
    	}
    	
    	inline ll Add(ll x,ll y){
    		Inc(x,y);return x;
    	}
    	
    	inline ll Sub(ll x,ll y){
    		Dec(x,y);return x;
    	}
    }
    using namespace ModCalc;
    
    inline ll read(){
    	ll s = 0,ww = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9'){if(ch == '-')ww = -1;ch = getchar();}
    	while('0' <= ch && ch <= '9'){s = 10 * s + ch - '0';ch = getchar();}
    	return s * ww;
    }
    
    inline void write(ll x){
    	if(x < 0)x = -x,putchar('-');
    	if(x > 9)write(x / 10);
    	putchar('0' + x % 10);
    }
    
    ll pn;
    ll pri[sqrtN+5],mu[sqrtN+5];
    bool isp[sqrtN+5];
    ll S[T+5];
    
    inline void Eular(){
    	mu[1] = 1;
    	for(rg ll i = 2;i <= sqrtN;i++)isp[i] = 1;
    	for(rg ll i = 2;i <= sqrtN;i++){
    		if(isp[i])pri[++pn] = i,mu[i] = -1;
    		for(rg ll j = 1;i * pri[j] <= sqrtN;j++){
    			isp[i*pri[j]] = 0;
    			if(i % pri[j])mu[i*pri[j]] = -mu[i];
    			else{
    				mu[i*pri[j]] = 0;
    				break;
    			}
    		}
    	}
    }
    
    inline ll s(ll n){
    	if(n <= T && S[n])return S[n];
    	ll L,R = 0;
    	ll ans = 0;
    	while(R < n){
    		L = R + 1,R = n / (n / L);
    		ans = (ans + (R - L + 1) * (n / L)) % mod;
    	}
    	if(n <= T)S[n] = ans;
    	return ans;
    }
    
    int main(){
    	Eular();
    	ll c = 1;
    	ll T = read();
    	while(T--){
    		printf("Case #%lld: ",c++);
    		ll n = read();
    		ll ans = 0;
    		for(rg ll i = 1;i * i <= n;i++)if(mu[i])ans = (ans + mu[i] * s(n/i/i)) % mod;
    		write((ans + mod) % mod),putchar('
    ');
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    笨办法学习python之hashmap
    python实现三级菜单源代码
    ql的python学习之路-day3
    ql的python学习之路-day2
    Spring的数据库开发
    Spring学习之Aspectj开发实现AOP
    spring学习之依赖注入DI与控制反转IOC
    spring学习之第一个spring程序
    spring学习之spring入门
    Java线程(一)——创建线程的两种方法
  • 原文地址:https://www.cnblogs.com/xh092113/p/12289949.html
Copyright © 2020-2023  润新知