标签:include register 玩意儿 strong long class 取值 判断 pre
定义\(f(n)\)为\(n\)所含质因子的最大幂指数。
例如\(f(2^33^25^411^2) = 4\ \) , \(\ f(3^57^3) = 5\),特别的,\(f(1) = 0\)。
现在有\(T\)组数据,每组数据输入两个数\(n\ ,\ m\),试求:
\[\sum_{i = 1}^n \sum_{j=1}^m f(\ gcd(i,j)\ )\]
数据范围:\(T \leq 10^4\) ; \(n,m \leq 10^7\)。\(\ \ \)原题网址:戳我
报告!我会莫比乌斯反演!
很好同学,那我们就直接跳到这一步吧......
令\(N = min(n,m)\),则:
\[ans = \sum_{T = 1}^N \lfloor \frac{n}{T} \rfloor \lfloor \frac{m}{T} \rfloor \sum_{d|T} \mu(\frac{T}{d})f(d)\]
显然前面数论分块就可以解决,关键是如何线性筛出这个玩意儿:
\[G(T) = \sum_{d|T} \mu(\frac{T}{d})f(d)\]
显然\(\mu(\frac{T}{d}) = 0\)的时候对答案是没有贡献的。
唯一分解:\(T = p_1^{x_1}p_2^{x_2}...p_k^{x_k}\) ,同理 \(d = p_1^{y_1}p_2^{y_2}...p_k^{y_k}\)。
那么根据\(\mu\)的定义,若\(\mu(\frac{T}{d}) \ne 0\)时 , \(x_i - y_i \leq 1\)。
我们考虑有贡献的项,分类讨论一下:
当存在\(x_i<x_j\)的时候,
由于\(f(d) = max\{y\}\)而\(y_i \leq y_j\),
所以无论\(y_i\)怎么取,\(f(d)\)的值都是不会变的。
所以无论\(y\)的取值情况如何,\(f(d)\)都是一个定值!
而\(x_i - y_i\)等于 \(0\) 或 \(1\) 时,在\(\mu(\frac{T}{d})\)中\(p_i^{x_i-y_i}\)的贡献刚好是相反的(为1和-1)。
所以无论\(f(d)\)怎么取,
非最大\(x\)的那些项的贡献都可以一一抵消。所以这种情况下答案一定是 \(0\)。
当不存在\(x_i < x_j\),即\(x_1=x_2=...x_k\)时:
先假设所有情况下\(f(d) = x\) , 那么答案就是 \(0\) , 理由见上。
但是存在一种情况\(f(d) = x-1\) , 就是当所有\(y\)都等于\(x-1\)的时候。
这个情况下多出来了一个-1,考虑把这个系数减去。
显然这个系数带\(\mu\)后等于\(-1\times \mu(\frac{T}{d}) = -\mu(p_1p_2...p_k) = (-1)^{k+1}\) 。
所以这种情况下答案为\((-1)^{k+1}\)。
所以线性筛的时候记录一下最小质因子的幂指数和最小值因子的指数次幂。
利用递推的思想,
每次得到 除去最小质因子外的数,
通过判断 这个数的最小因子幂指数 与 当前最小因子幂指数 是否相等,
就可以判断出当前答案应该是 \(0\) 还是从之前的答案\(G\) 转移。复杂度:\(O(n + T\sqrt{n})\)
#include<bits/stdc++.h>
#define RG register
#define IL inline
#define _ 10000007
using namespace std;
int n,m,N,low[_],pri[_],js[_],tot; bool Is[_]; long long ans,G[_];
IL void Seive(){
Is[1] = true ; tot = 0 ; G[1] = 0;
for(RG int i = 2; i <= N; i ++){
if(!Is[i]) pri[++tot] = i , G[i] = js[i] = 1 , low[i] = i;
for(RG int j = 1; j <= tot && i * pri[j] <= N; j ++){
Is[i * pri[j]] = true ;
if(i % pri[j] == 0){
low[i * pri[j]] = low[i] * pri[j] ;
js[i * pri[j]] = js[i] + 1 ;
if(low[i] == i) G[i * pri[j]] = 1 ;
else G[i*pri[j]] = (js[i*pri[j]] == js[i/low[i]]) ? - G[i/low[i]] : 0 ;
break ;
}
low[i * pri[j]] = pri[j] ; js[i * pri[j]] = 1 ;
G[i * pri[j]] = (js[i] == 1) ? -G[i] : 0 ;
}
}
for(RG int i = 1; i <= N; i ++) G[i] += G[i - 1] ;
}
int main(){
N = 10000000 ; Seive() ;
RG int Cat; cin >> Cat ;
while(Cat -- ){
scanf("%d %d\n",&n,&m) ; N = min(n , m) ;
ans = 0 ;
for(RG int l = 1,r; l <= N; l = r + 1){
r = min(N , min(n / (n/l) , m / (m/l))) ;
ans = ans + 1ll * (n / l) * (m / l) * (G[r] - G[l-1]) ;
}
printf("%lld\n" , ans) ;
}return 0 ;
}
标签:include register 玩意儿 strong long class 取值 判断 pre
原文地址:https://www.cnblogs.com/GuessYCB/p/8810429.html