zoukankan      html  css  js  c++  java
  • [SDOI2015]约数个数和

    题意

    (sumlimits_i^n sumlimits_j^m d(ij))其中(d(x))(x)的约数个数

    想法

    看到这个柿子想到的就是莫反了。
    有这样一个结论

    ( d(xy)= sumlimits_{i|x} sumlimits_{j|y}[gcd(i,j) == 1]  )

    所以变形原柿子(n > m)

    (sumlimits_i^n sumlimits_j^m d(ij))

    (sumlimits_i^n sumlimits_j^m sumlimits_{x|i} sumlimits_{y|j}[gcd(x,y) == 1]))

    (mu(x)) 的性质:

    ([n == 1] = sumlimits_{d|n}mu(d))

    (sumlimits_i^n sumlimits_j^m sumlimits_{x|i} sumlimits_{y|j}sumlimits_{d|gcd(x,y)}mu(d)))

    改为枚举(d)-

    (sumlimits_{d = 1}^nsumlimits_{x = 1}^{n/d}sumlimits_{i = 1}^{n/d/x}sumlimits_{y = 1}^{m/d}sumlimits_{j = 1}^{m/d/y}mu(d))

    (sumlimits_{d = 1}^nsumlimits_{x = 1}^{n/d}lfloorfrac{n}{d * x} floorsumlimits_{y = 1}^{n/d}lfloorfrac{m}{d * y} floormu(d))

    (sumlimits_{d = 1}^nmu(d)sumlimits_{x = 1}^{n/d}lfloorfrac{lfloorfrac{n}{d} floor}{x} floorsumlimits_{y = 1}^{m/d}lfloorfrac{lfloorfrac{m}{d} floor}{y} floor)

    后面两个(sum)可以整除分块

    复杂度(O(Nsqrt(N)))

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    int read(){
    	char cc = getchar(); int cn = 0, flus = 1;
    	while(cc < '0' || cc > '9'){
        	if(cc == '-') flus = -flus;
    		cc = getchar();
    	}
    	while(cc >= '0' && cc <= '9')
    	    cn = cn * 10 + cc - '0', cc = getchar();
    	return cn * flus;
    }
    const int N = 50000 + 5;
    int u[N], sum[N], pm[N], n, f[N], top;
    bool isp[N];
    void init(){
    	u[1] = 1;
    	for(int i = 2; i <= n; i++){
    		if(!isp[i]){
    			pm[++top] = i;
    			u[i] = -1;
    		}
    		for(int j = 1; j <= top; j++){
    			int p = pm[j];
    			if(p * i > n) break;
    			if(i % p == 0){
    				isp[p * i] = 1;
    				break;
    			}
    			isp[p * i] = 1;
    			u[p * i] = u[p] * u[i];
    		}
    	}
    	int l, r;
    	for(int i = 1; i <= n; i++){
    		for(l = 1; l <= i; l = r + 1){
    			r = i/(i/l);
    			f[i] += (r - l + 1) * (i/l);
    		}
    		sum[i] = sum[i - 1] + u[i];
    	}
    }
    int solve(int x, int y){
    	if(x > y) swap(x, y);
    	int ans = 0, l = 1, r;
    	for(l = 1; l <= x; l = r + 1){
    		r = min((x/(x/l)), (y/(y/l)));
    		ans += (sum[r] - sum[l - 1]) * f[x/l] * f[y/l];
    	}
    	return ans;
    }
    signed main()
    {
    	n = 50000;
    	init();
    	int T = read(), a, b;
    	while(T--){
    		a = read(); b = read();
    		printf("%lld
    ", solve(a, b));
    	}
    	return 0;
    }
    
  • 相关阅读:
    【codecombat】 试玩全攻略 第九关 循环又循环
    【codecombat】 试玩全攻略 第十三关 已知敌人
    【codecombat】 试玩全攻略 第十一关 再次迷宫经历
    【codecombat】 试玩全攻略 第六关 cell commentary
    【codecombat】 试玩全攻略 第八关 火舞
    【codecombat】 试玩全攻略 第十二关 恐惧之门
    【codecombat】 试玩全攻略 第十四关 已知敌人
    苹果apns推送总结
    Xcode 提升速度小技巧
    UITextField 限制输入字数
  • 原文地址:https://www.cnblogs.com/dixiao/p/14250973.html
Copyright © 2011-2022 走看看