zoukankan      html  css  js  c++  java
  • [洛谷P3768]简单的数学题(杜教筛)

    题面

    https://www.luogu.com.cn/problem/P3768

    题解

    前置知识

    看到gcd,开始反演

    [{sumlimits_{i=1}^{n}}{sumlimits_{j=1}^{n}}ij(i,j) ]

    [={sumlimits_{i=1}^{n}}{sumlimits_{j=1}^{n}}ij{sumlimits_{p|(i,j)}}{mu(p)} ]

    [={sumlimits_{i=1}^{n}}{sumlimits_{j=1}^{n}}ij{sumlimits_{p|i,p|j}}{mu(p)} ]

    [={sumlimits_{p}}{mu(p)}{sumlimits_{i=1}^{n}}{sumlimits_{j=1}^{n}}ij[p|i][p|j] ]

    [={sumlimits_{p}}{mu(p)}*p^2*({frac{{lfloor}{frac{n}{p}}{ floor}({lfloor}{frac{n}{p}}{ floor}+1)}{2}})^2① ]

    然后使用数论分块,剩下的问题就只是求解(f(p)={mu(p)}*p^2)的前缀和sf了。

    (g(p)=p^2,h(p)=p^3)(这里g,h的作用详见前置知识->杜教筛)就可以使用杜教筛求解了。值得注意的是,杜教筛可以一次性求出所有的(sf({lfloor}{frac{n}{i}}{ floor})(1{leq}i{leq}n)),而数论分块求①式的时候,也恰好只用到了这些sf值(分块时每一块的右端点R就是通过n/(n/L)得到的,所以每一个右端点都是({lfloor}{frac{n}{i}}{ floor}(1{leq}i{leq}n))中的一个),所以总体相当于只需要做一次杜教筛,就(O(n^{frac{2}{3}}))解决本题。

    代码

    • P.S.一定要注意爆long long的问题。虽然(p^2)并不会爆,但是(n^2)会爆。
    • 如果此题的p再大一些,使得(p^2)也会爆的话,就必须要使用O(1)快速乘了。
    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define D 4641600
    #define M 2160
    #define ll long long
    #define rg register
    
    ll mod;
    
    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 < 0)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;
    
    ll sphi[D+M+5],pri[D/5+5];
    ll n,pn,v2,v3;
    bool isp[D+5];
    
    inline ll F(ll x){
    	x = x % mod * ((x + 1) % mod) % mod * v2 % mod;
    	return x * x % mod;
    }
    
    inline void Eular(){
    	sphi[1] = 1;
    	for(rg ll i = 2;i <= D;i++)isp[i] = 1;
    	for(rg ll i = 2;i <= D;i++){  
    		if(isp[i])pri[++pn] = i,sphi[i] = i - 1;
    		for(rg ll j = 1;i * pri[j] <= D;j++){
    			isp[i*pri[j]] = 0;
    			if(i % pri[j])sphi[i*pri[j]] = sphi[i] * sphi[pri[j]];
    			else{
    				sphi[i*pri[j]] = sphi[i] * pri[j];
    				break;
    			}
    		}
    	}
    	for(rg ll i = 1;i <= D;i++)sphi[i] = sphi[i] * i % mod * i % mod;
    	for(rg ll i = 2;i <= D;i++)Inc(sphi[i],sphi[i-1]); 
    }
    
    inline ll id(ll x){
    	if(x <= D)return x;
    	return D + n / x;
    } 
    
    inline ll sg(ll x){
    	return (x % mod) * ((x + 1) % mod) % mod * (((x << 1) | 1) % mod) % mod * v2 % mod * v3 % mod;
    }
    
    inline ll sumf(ll x){
    	if(sphi[id(x)])return sphi[id(x)];
    	ll ans = F(x),L,R = 1;
    	while(R < x){
    		L = R + 1,R = x / (x / L);
    		Dec(ans,Sub(sg(R),sg(L-1)) * sumf(x/L) % mod);
    	}
    	return sphi[id(x)] = ans;	
    }
    
    int main(){
    	scanf("%lld%lld",&mod,&n);
    	Eular();
    	v2 = (mod + 1) >> 1;
    	v3 = mod % 3 == 1 ? ((mod << 1) | 1) / 3 : (mod + 1) / 3;
    	ll ans = 0,L,R = 0;
    	while(R < n){
    		L = R + 1;
    		R = n / (n / L);
    		Inc(ans,Sub(sumf(R),sumf(L-1)) * F(n/L) % mod);
    	}
    	cout << ans << endl;
    	return 0;
    }
    
    
  • 相关阅读:
    java保留字
    12个不可不知的Sublime Text应用技巧和诀窍
    人生准则
    基于Android 的蓝牙A2DP 功能的实现
    蓝牙协议栈详解
    我的2015计划
    今日学习
    滤波器介绍
    STLINK V2安装使用详解
    javascript闭包
  • 原文地址:https://www.cnblogs.com/xh092113/p/12291876.html
Copyright © 2011-2022 走看看