• P6070 [RC-02] GCD [杜教筛,莫比乌斯反演]


    没啥好说的,杜教筛板子题。

    [sum_{i=1}^{N} sum_{j=1}^{N}sum_{p=1}^{lfloor frac{N}{j} floor}sum_{q=1}^{lfloor frac{N}{j} floor} [gcd(i,j)==1][gcd(p,q)==1] ]

    容易发现,我们枚举 (j) 其实是相当于枚举 (gcd)
    才不是枚举题目

    然后式子可以变成

    [sum_{i=1}^{N}sum_{p=1}^{N}sum_{q=1}^{N} [gcd(i,p,q)==1] ]

    然后套路式的枚举 (gcd) 依旧不是枚举题目

    [sum_{d=1}^{N}sum_{i=1}^{N}sum_{p=1}^{N}sum_{q=1}^{N}[gcd(i,p,q)==d] ]

    熟悉的形式,其实就等于

    [sum_{d=1}^{N}sum_{i=1}^{lfloor frac{N}{d} floor} sum_{p=1}^{lfloor frac{N}{d} floor} sum_{q=1}^{lfloor frac{N}{d} floor} mu(d) ]

    [sum_{d=1}^{N} mu(d) lfloor frac{N}{d} floor^3 ]

    然后整除分块就完了,由于 (N) 比较大,大力杜教筛就完事了,话说我好像是这题除掉出题人的最优解

    // powered by c++11
    // by Isaunoya
    #include<bits/stdc++.h>
    #define rep(i , x , y) for(register int i = (x) ; i <= (y) ; ++ i)
    #define Rep(i , x , y) for(register int i = (x) ; i >= (y) ; -- i)
    using namespace std ;
    using db = double ;
    using ll = long long ;
    using uint = unsigned int ;
    #define int long long
    using pii = pair < int , int > ;
    #define ve vector
    #define Tp template
    #define all(v) v.begin() , v.end()
    #define sz(v) ((int)v.size())
    #define pb emplace_back
    #define fir first
    #define sec second
    // the cmin && cmax
    Tp < class T > void cmax(T & x , const T & y) { if(x < y) x = y ; }
    Tp < class T > void cmin(T & x , const T & y) { if(x > y) x = y ; }
    // sort , unique , reverse
    Tp < class T > void sort(ve < T > & v) { sort(all(v)) ; }
    Tp < class T > void unique(ve < T > & v) { sort(all(v)) ; v.erase(unique(all(v)) , v.end()) ; }
    Tp < class T > void reverse(ve < T > & v) { reverse(all(v)) ; }
    const int SZ = 0x191981 ;
    struct FILEIN {
    	~ FILEIN () {} char qwq[SZ] , * S = qwq , * T = qwq , ch ;
    	char GETC() { return (S == T) && (T = (S = qwq) + fread(qwq , 1 , SZ , stdin) , S == T) ? EOF : * S ++ ; }
    	FILEIN & operator >> (char & c) { while(isspace(c = GETC())) ; return * this ; }
    	FILEIN & operator >> (string & s) {
    		while(isspace(ch = GETC())) ; s = ch ;
    		while(! isspace(ch = GETC())) s += ch ; return * this ;
    	}
    	Tp < class T > void read(T & x) {
    		bool sign = 1 ; while((ch = GETC()) < 0x30) if(ch == 0x2d) sign = 0 ;
    		x = (ch ^ 0x30) ; while((ch = GETC()) > 0x2f) x = x * 0xa + (ch ^ 0x30) ;
    		x = sign ? x : -x ;
    	}
    	FILEIN & operator >> (int & x) { return read(x) , * this ; }
    	FILEIN & operator >> (signed & x) { return read(x) , * this ; }
    	FILEIN & operator >> (unsigned & x) { return read(x) , * this ; }
    } in ;
    struct FILEOUT { const static int LIMIT = 0x114514 ;
    	char quq[SZ] , ST[0x114] ; signed sz , O ;
    	~ FILEOUT () { sz = O = 0 ; }
    	void flush() { fwrite(quq , 1 , O , stdout) ; fflush(stdout) ; O = 0 ; }
    	FILEOUT & operator << (char c) { return quq[O ++] = c , * this ; }
    	FILEOUT & operator << (string str) {
    		if(O > LIMIT) flush() ; for(char c : str) quq[O ++] = c ; return * this ;
    	}
    	Tp < class T > void write(T x) {
    		if(O > LIMIT) flush() ; if(x < 0) { quq[O ++] = 0x2d ; x = -x ; }
    		do { ST[++ sz] = x % 0xa ^ 0x30 ; x /= 0xa ; } while(x) ;
    		while(sz) quq[O ++] = ST[sz --] ; return ;
    	}
    	FILEOUT & operator << (int x) { return write(x) , * this ; }
    	FILEOUT & operator << (signed x) { return write(x) , * this ; }
    	FILEOUT & operator << (unsigned x) { return write(x) , * this ; }
    } out ;
    
    const int maxn = 5e5 ;
    int mu[maxn + 10] ;
    const int mod = 998244353 ;
    map < int , int > _mu ;
    int getmu(int x) {
    	if(x <= maxn) return mu[x] ;
    	if(_mu[x]) return _mu[x] ;
    	int ans = 1 ;
    	int l = 2 , r = 0 ;
    	for( ; l <= x ; l = r + 1) {
    		r = x / (x / l) ;
    		ans -= getmu(x / l) * (r - l + 1) ;
    		ans = (ans + mod) % mod ;
    	}
    	return _mu[x] = ans ;
    }
    signed main() {
    #ifdef _WIN64
    	freopen("testdata.in" , "r" , stdin) ;
    #else
    	ios_base :: sync_with_stdio(false) ;
    	cin.tie(nullptr) , cout.tie(nullptr) ;
    #endif
    // code begin.
    	mu[1] = 1 ;
    	for(int i = 1 ; i <= maxn ; i ++)
    		for(int j = i + i ; j <= maxn ; j += i) 
    			mu[j] -= mu[i] ;
    	for(int i = 2 ; i <= maxn ; i ++)
    		mu[i] = (mu[i] + mu[i - 1]) % mod ;
    	int n ;
    	in >> n ;
    	int l = 1 , r = 0 ;
    	int ans = 0 ;
    	for( ; l <= n ; l = r + 1) {
    		r = n / (n / l) ;
    		int qwq = (n / l) * (n / l) % mod * (n / l) % mod ;
    		ans = (ans + (getmu(r) - getmu(l - 1) + mod) % mod * qwq % mod) % mod ;
    	}
    	out << ans << '
    ' ;
    	return out.flush() , 0 ;
    // code end.
    }
    
  • 相关阅读:
    第三十五课、文本编辑器中的数据存取------------------狄泰软件学院
    第三十四课、缓冲区操作与目录操作------------------狄泰软件学院
    第三十三课、文件流和数据流------------------狄泰软件学院
    Machine Learning in Action(6) AdaBoost算法
    Machine Learning in Action(5) SVM算法
    machine learning for hacker记录(4) 智能邮箱(排序学习&推荐系统)
    linux mysql乱码问题
    php7+新特性
    shell学习(6)- curl
    shell学习(5)- sort
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/12267408.html
Copyright © 2020-2023  润新知