zoukankan      html  css  js  c++  java
  • P1829 [国家集训队]Crash的数字表格 / JZPTAB

    (color{#0066ff}{ 题目描述 })

    今天的数学课上,Crash小朋友学习了最小公倍数(Least Common Multiple)。对于两个正整数a和b,LCM(a, b)表示能同时整除a和b的最小正整数。例如,LCM(6, 8) = 24。

    回到家后,Crash还在想着课上学的东西,为了研究最小公倍数,他画了一张NM的表格。每个格子里写了一个数字,其中第i行第j列的那个格子里写着数为LCM(i, j)。一个45的表格如下:

    1    2    3    4    5
    2    2    6    4    10
    3    6    3    12    15
    4    4    12    4    20
    

    看着这个表格,Crash想到了很多可以思考的问题。不过他最想解决的问题却是一个十分简单的问题:这个表格中所有数的和是多少。当N和M很大时,Crash就束手无策了,因此他找到了聪明的你用程序帮他解决这个问题。由于最终结果可能会很大,Crash只想知道表格里所有数的和mod20101009的值。

    (color{#0066ff}{输入格式})

    输入的第一行包含两个正整数,分别表示N和M。

    (color{#0066ff}{输出格式})

    输出一个正整数,表示表格中所有数的和mod20101009的值。

    (color{#0066ff}{输入样例})

    4 5
    

    (color{#0066ff}{输出样例})

    122
    

    (color{#0066ff}{数据范围与提示})

    30%的数据满足(N, M≤ 10^3。)

    70%的数据满足(N, M≤ 10^5。)

    100%的数据满足(N, M≤ 10^7。)

    (color{#0066ff}{ 题解 })

    题目就是要求

    [sum_{i=1}^n sum_{j=1}^m lcm(i,j) ]

    显然要转为gcd的东西

    [sum_{i=1}^n sum_{j=1}^m frac {i*j} {gcd(i,j)} ]

    gcd套路,考虑枚举gcd

    [sum_{d=1}^{min(n,m)} sum_{i=1}^n sum_{j=1}^m [gcd(i,j)==d] frac {i*j} {d} ]

    老套路,把d除上去,注意后面的(i*j),各除去了一个d,所以要乘回来(d^2)

    [sum_{d=1}^{min(n,m)} sum_{i=1}^{lfloorfrac{n}{d} floor} sum_{j=1}^{lfloorfrac{m}{d} floor} [gcd(i,j)==1] i*j*d ]

    然后发现d可以提出来

    [sum_{d=1}^{min(n,m)} dsum_{i=1}^{lfloorfrac{n}{d} floor} sum_{j=1}^{lfloorfrac{m}{d} floor} [gcd(i,j)==1] i*j ]

    我们令(f(x, y))等于后面那一坨,即

    [f(a,b)=sum_{i=1}^{a} sum_{j=1}^{b} [gcd(i,j)==1] i*j ]

    看到这种形式,继续利用(mu * i =e),来化简(f)

    [sum_{i=1}^{a} sum_{j=1}^{b} sum_{d|gcd(i,j)} mu(d)* i*j ]

    然后枚举gcd

    [sum_{d=1}^{min(a,b)} mu(d) sum_{d|i}^{a} sum_{d|j}^b i*j ]

    后面的显然不好枚举,考虑(i=p_1d,j=p_2d),枚举(p_1,p_2)

    [sum_{d=1}^{min(a,b)} mu(d) sum_{i=1}^{lfloorfrac a k floor} sum_{j=1}^{lfloorfrac b k floor} i*d*j*d ]

    然后我们又可以开心的把d提出来了

    [sum_{d=1}^{min(a,b)} mu(d) * d^2 sum_{i=1}^{lfloorfrac a k floor} sum_{j=1}^{lfloorfrac b k floor} i*j ]

    后面的东西好像很好求呢

    [令g(a,b)=sum_{i=1}^asum_{j=1}^bi*j=frac{a*(a+1)}{2}*frac{b*(b+1)}{2} ]

    嗯,(O(1))就出来了

    至此,本题就完了

    总结一下

    [sum_{i=1}^n sum_{j=1}^m lcm(i,j)=sum_{d=1}^{min(n,m)} d *f(lfloorfrac{n}{d} floor,lfloorfrac{m}{d} floor) ]

    [f(a,b)=sum_{d=1}^{min(a,b)} mu(d) * d^2* g(lfloorfrac a k floor,lfloorfrac b k floor) ]

    [g(a,b)=frac{a*(a+1)}{2}*frac{b*(b+1)}{2} ]

    最后一个(O(1))求,前两个数列分块即可

    #include<bits/stdc++.h>
    #define LL long long
    LL in() {
    	char ch; LL x = 0, f = 1;
    	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    	return x * f;
    }
    const int mod = 20101009;
    const int maxn = 1e7 + 10;
    LL pri[maxn], tot, mu[maxn], s[maxn];
    bool vis[maxn];
    
    void predoit() {
    	mu[1] = 1;
    	for(int i = 2; i < maxn; i++) {
    		if(!vis[i]) pri[++tot] = i, mu[i] = -1;
    		for(int j = 1; j <= tot && (LL)i * pri[j] < maxn; j++) {
    			vis[i * pri[j]] = true;
    			if(i % pri[j] == 0) break;
    			else mu[i * pri[j]] = -mu[i];
    		}
    	}
    	for(int i = 1; i < maxn; i++) s[i] = (s[i - 1] + 1LL * mu[i] * i * i) % mod;
    }
    LL getsum1(LL l, LL r) {
    	return ((l + r) * (r - l + 1) >> 1LL) % mod;
    }
    LL getsum2(LL a, LL b) {
    	return (((a * (a + 1) >> 1LL) % mod) * ((b * (b + 1) >> 1LL) % mod)) % mod;
    }
    LL getans(LL a, LL b) {
    	LL ans = 0;
    	for(LL l = 1, r; l <= std::min(a, b); l = r + 1) {
    		r = std::min(a / (a / l), b / (b / l));
    		(ans += ((((s[r] - s[l - 1]) % mod + mod) % mod) * getsum2(a / l, b / l) % mod)) %= mod;
    	}
    	return ans;
    }
    
    
    LL work(LL a, LL b) {
    	LL ans = 0;
    	for(LL l = 1, r; l <= std::min(a, b); l = r + 1) {
    		r = std::min(a / (a / l), b / (b / l));
    		(ans += getsum1(l, r) * getans(a / l, b / l) % mod) %= mod;
    	}
    	return ans;
    }
    
    
    int main() {
    	predoit();
    	int n = in(), m = in();
    	printf("%lld
    ", work(n, m));
    	return 0;
    }
    
  • 相关阅读:
    20145214 《信息安全系统设计基础》实验五 网络通信
    20145214 《信息安全系统设计基础》第12周学习总结
    20145214 《信息安全系统设计基础》第11周学习总结
    20145214 《信息安全系统设计基础》实验四 驱动程序设计
    20145214 《信息安全系统设计基础》实验三 实时系统的移植
    20145214 《信息安全系统设计基础》第10周学习总结
    20145214 《信息安全系统设计基础》实验二 固件开发
    20145214 《信息安全系统设计基础》第9周学习总结
    20145325张梓靖 《网络对抗技术》 第2周学习总结
    20145325 《信息安全系统设计基础》实验四 外设驱动程序设计(添加代码分析)
  • 原文地址:https://www.cnblogs.com/olinr/p/10294278.html
Copyright © 2011-2022 走看看