退役OIer回来受虐啦
一些定义
μ ( x ) = { 1 x > 1 ( − 1 ) n x = ∏ i = 1 n P i 0 o t h e r w i s e \mu(x) = \begin{cases} 1 & x > 1 \\ (-1)^n & x = \prod _ {i=1} ^ {n} P_{i}\\ 0 & otherwise \end{cases} μ(x)=⎩ ⎨ ⎧1(−1)n0x>1x=∏i=1nPiotherwise
φ ( n ) = ∑ i = 1 n [ g c d ( i , n ) = 1 ] \varphi(n)=\sum_{i=1}^{n}\ [gcd(i,n)=1] φ(n)=i=1∑n [gcd(i,n)=1]
ε ( n ) = [ n = 1 ] \varepsilon(n)=\ [n=1] ε(n)= [n=1]
一些性质
∑ d ∣ n μ ( d ) = ε ( n ) \sum_{d|n}\mu(d)=\varepsilon(n) d∣n∑μ(d)=ε(n)
即 μ ∗ 1 = ε \mu\ast1=\varepsilon μ∗1=ε
推广一下:
[ g c d ( i , j ) = 1 ] = ∑ d ∣ g c d ( i , j ) μ ( d ) [gcd(i,j)=1]=\sum_{d|gcd(i,j)}\mu(d) [gcd(i,j)=1]=d∣gcd(i,j)∑μ(d)
φ ∗ 1 = i d \varphi \ast 1=id φ∗1=id
莫比乌斯变换
f ( n ) = ∑ d ∣ n g ( d ) ⇒ g ( n ) = ∑ d ∣ n f ( d ) μ ( n d ) f(n)=\sum_{d|n} g(d)\ \Rightarrow\ g(n)=\sum_{d|n}f(d)\mu(\frac{n}{d}) f(n)=d∣n∑g(d) ⇒ g(n)=d∣n∑f(d)μ(dn)
f ( n ) = ∑ n ∣ d g ( d ) ⇒ g ( n ) = ∑ n ∣ d μ ( d n ) f ( d ) f(n)=\sum_{n|d}g(d)\ \Rightarrow\ g(n)=\sum_{n|d}\mu(\frac{d}{n})f(d) f(n)=n∣d∑g(d) ⇒ g(n)=n∣d∑μ(nd)f(d)
例题
[HAOI2011] Problem b
题目描述
对于给出的 n n n 个询问,每次求有多少个数对 ( x , y ) (x,y) (x,y),满足 a ≤ x ≤ b a \le x \le b a≤x≤b, c ≤ y ≤ d c \le y \le d c≤y≤d,且 gcd ( x , y ) = k \gcd(x,y) = k gcd(x,y)=k, gcd ( x , y ) \gcd(x,y) gcd(x,y) 函数为 x x x 和 y y y 的最大公约数。
输入格式
第一行一个整数 n n n,接下来 n n n 行每行五个整数,分别表示 a , b , c , d , k a,b,c,d,k a,b,c,d,k。
输出格式
共 n n n 行,每行一个整数表示满足要求的数对 ( x , y ) (x,y) (x,y) 的个数。
样例 #1
样例输入 #1
2
2 5 1 5 1
1 5 1 5 2
样例输出 #1
14
3
提示
对于 100 % 100\% 100% 的数据满足: 1 ≤ n , k ≤ 5 × 1 0 4 1 \le n,k \le 5 \times 10^4 1≤n,k≤5×104, 1 ≤ a ≤ b ≤ 5 × 1 0 4 1 \le a \le b \le 5 \times 10^4 1≤a≤b≤5×104, 1 ≤ c ≤ d ≤ 5 × 1 0 4 1 \le c \le d \le 5 \times 10^4 1≤c≤d≤5×104。
题解
根据容斥原理,原式可以分成 4 块来处理,每一块的式子都为
∑ i = 1 n ∑ j = 1 m [ gcd ( i , j ) = k ] \sum_{i=1}^{n}\sum_{j=1}^{m}[\gcd(i,j)=k] i=1∑nj=1∑m[gcd(i,j)=k]
考虑化简该式子
∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ m k ⌋ ε ( gcd ( i , j ) ) \sum_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{k}\rfloor}\varepsilon(\gcd(i,j)) i=1∑⌊kn⌋j=1∑⌊km⌋ε(gcd(i,j))
将 ε \varepsilon ε 函数展开得到
∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ m k ⌋ ∑ d ∣ gcd ( i , j ) μ ( d ) \displaystyle\sum_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{k}\rfloor}\sum_{d\mid \gcd(i,j)}\mu(d) i=1∑⌊kn⌋j=1∑⌊km⌋d∣gcd(i,j)∑μ(d)
变换求和顺序,先枚举 d ∣ gcd ( i , j ) d\mid \gcd(i,j) d∣gcd(i,j) 可得
∑ d = 1 μ ( d ) ∑ i = 1 ⌊ n k ⌋ [ d ∣ i ] ∑ j = 1 ⌊ m k ⌋ [ d ∣ j ] \displaystyle\sum_{d=1}\mu(d)\sum_{i=1}^{\lfloor\frac{n}{k}\rfloor}[d\mid i]\sum_{j=1}^{\lfloor\frac{m}{k}\rfloor}[d\mid j] d=1∑μ(d)i=1∑⌊kn⌋[d∣i]j=1∑⌊km⌋[d∣j]
易知 1 ∼ ⌊ n k ⌋ 1\sim\lfloor\dfrac{n}{k}\rfloor 1∼⌊kn⌋ 中 d d d 的倍数有 ⌊ n k d ⌋ \lfloor\dfrac{n}{kd}\rfloor ⌊kdn⌋ 个,故原式化为
∑ d = 1 min ( ⌊ n k ⌋ , ⌊ m k ⌋ ) μ ( d ) ⌊ n k d ⌋ ⌊ m k d ⌋ \displaystyle\sum_{d=1}^{\min(\lfloor \frac{n}{k}\rfloor,\lfloor \frac{m}{k}\rfloor)}\mu(d)\lfloor\frac{n}{kd}\rfloor\lfloor\frac{m}{kd}\rfloor d=1∑min(⌊kn⌋,⌊km⌋)μ(d)⌊kdn⌋⌊kdm⌋
整除分块即可求解
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+77;
int mu[N],sum[N];
vector<int> p;
bool bz[N];
void init(int n)
{mu[1]=1;for(int i=2; i<=n; i++){if(!bz[i]){mu[i]=-1;p.push_back(i);}for(auto j:p){if(j*i>n) break;bz[i*j]=1;if(i%j==0) break;else mu[i*j]=-mu[i];}}for(int i=1; i<=n; i++) sum[i]=sum[i-1]+mu[i];
}
int solve(int n,int m,int k)
{int ans=0;n/=k; m/=k;for(int l=1,r; l<=min(n,m); l=r+1){r=min((n/(n/l)),(m/(m/l)));ans+=(n/l)*(m/l)*(sum[r]-sum[l-1]);}return ans;
}
void O_o()
{int a,b,c,d,k;cin>>a>>b>>c>>d>>k;cout<<solve(b,d,k)-solve(a-1,d,k)-solve(b,c-1,k)+solve(a-1,c-1,k)<<"\n";
}
signed main()
{ios::sync_with_stdio(false); cin.tie(0),cout.tie(0);int T=1;init(50000);cin>>T;while(T--){O_o();}
}
[国家集训队] Crash的数字表格 / JZPTAB
题目描述
今天的数学课上,Crash 小朋友学习了最小公倍数(Least Common Multiple)。对于两个正整数 a a a 和 b b b, lcm ( a , b ) \text{lcm}(a,b) lcm(a,b) 表示能同时被 a a a 和 b b b 整除的最小正整数。例如, lcm ( 6 , 8 ) = 24 \text{lcm}(6, 8) = 24 lcm(6,8)=24。
回到家后,Crash 还在想着课上学的东西,为了研究最小公倍数,他画了一张 $ n \times m$ 的表格。每个格子里写了一个数字,其中第 i i i 行第 j j j 列的那个格子里写着数为 lcm ( i , j ) \text{lcm}(i, j) lcm(i,j)。
看着这个表格,Crash 想到了很多可以思考的问题。不过他最想解决的问题却是一个十分简单的问题:这个表格中所有数的和是多少。当 n n n 和 m m m 很大时,Crash 就束手无策了,因此他找到了聪明的你用程序帮他解决这个问题。由于最终结果可能会很大,Crash 只想知道表格里所有数的和对 20101009 20101009 20101009 取模后的值。
输入格式
输入包含一行两个整数,分别表示 n n n 和 m m m。
输出格式
输出一个正整数,表示表格中所有数的和对 20101009 20101009 20101009 取模后的值。
样例 #1
样例输入 #1
4 5
样例输出 #1
122
提示
样例输入输出 1 解释
该表格为:
1 1 1 | 2 2 2 | 3 3 3 | 4 4 4 | 5 5 5 |
---|---|---|---|---|
2 2 2 | 2 2 2 | 6 6 6 | 4 4 4 | 10 10 10 |
3 3 3 | 6 6 6 | 3 3 3 | 12 12 12 | 15 15 15 |
4 4 4 | 4 4 4 | 12 12 12 | 4 4 4 | 20 20 20 |
数据规模与约定
- 对于 30 % 30\% 30% 的数据,保证 n , m ≤ 1 0 3 n, m \le 10^3 n,m≤103。
- 对于 70 % 70\% 70% 的数据,保证 n , m ≤ 1 0 5 n, m \le 10^5 n,m≤105。
- 对于 100 % 100\% 100% 的数据,保证 1 ≤ n , m ≤ 1 0 7 1\le n,m \le 10^7 1≤n,m≤107。
题解
∑ i = 1 n ∑ j = 1 m l c m ( i , j ) = ∑ i = 1 n ∑ j = 1 m i ⋅ j g c d ( i , j ) = ∑ i = 1 n ∑ j = 1 m ∑ d = g c d ( i , j ) i ⋅ j d = ∑ d = 1 m i n ( n , m ) ∑ d ∣ i n ∑ d ∣ j m [ g c d ( i , j ) = d ] i ⋅ j d = ∑ d = 1 m i n ( n , m ) d ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ [ g c d ( i , j ) = 1 ] i j \sum_{i=1}^{n}\sum_{j=1}^{m} lcm(i,j)\\ =\sum_{i=1}^{n}\sum_{j=1}^{m} \frac{i\cdot j}{gcd(i,j)}\\ =\sum_{i=1}^{n}\sum_{j=1}^{m}\sum_{d=gcd(i,j)} \frac{i\cdot j}{d}\\ =\sum_{d=1}^{min(n,m)}\sum_{d|i}^{n}\sum_{d|j}^{m} [gcd(i,j)=d]\frac{i\cdot j}{d}\\ =\sum_{d=1}^{min(n,m)}d\ \sum_{i=1}^{\left\lfloor \frac{n}{d} \right\rfloor}\sum_{j=1}^{\left\lfloor \frac{m}{d} \right\rfloor} [gcd(i,j)=1]i j i=1∑nj=1∑mlcm(i,j)=i=1∑nj=1∑mgcd(i,j)i⋅j=i=1∑nj=1∑md=gcd(i,j)∑di⋅j=d=1∑min(n,m)d∣i∑nd∣j∑m[gcd(i,j)=d]di⋅j=d=1∑min(n,m)d i=1∑⌊dn⌋j=1∑⌊dm⌋[gcd(i,j)=1]ij
令 S ( n , m ) = ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = 1 ] i j S(n,m)=\sum_{i=1}^{n}\sum_{j=1}^{m} [gcd(i,j)=1]i j S(n,m)=∑i=1n∑j=1m[gcd(i,j)=1]ij
S ( n , m ) = ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = 1 ] i j = ∑ d = 1 n ∑ d ∣ i n ∑ d ∣ j m μ ( d ) ⋅ i ⋅ j = ∑ d = 1 n μ ( d ) ⋅ d 2 ⋅ ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ i ⋅ j S(n,m)=\sum_{i=1}^{n}\sum_{j=1}^{m} [gcd(i,j)=1]i j\\ =\sum_{d=1}^n\sum_{d\mid i}^n\sum_{d\mid j}^m\mu(d)\cdot i\cdot j\\ =\sum_{d=1}^n\mu(d)\cdot d^2\cdot\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}i\cdot j S(n,m)=i=1∑nj=1∑m[gcd(i,j)=1]ij=d=1∑nd∣i∑nd∣j∑mμ(d)⋅i⋅j=d=1∑nμ(d)⋅d2⋅i=1∑⌊dn⌋j=1∑⌊dm⌋i⋅j
观察上式,前半段可以预处理前缀和;后半段又是一个范围内数对之和,记
g ( n , m ) = ∑ i = 1 n ∑ j = 1 m i ⋅ j = n ⋅ ( n + 1 ) 2 × m ⋅ ( m + 1 ) 2 g(n,m)=\sum_{i=1}^n\sum_{j=1}^m i\cdot j=\frac{n\cdot(n+1)}{2}\times\frac{m\cdot(m+1)}{2} g(n,m)=i=1∑nj=1∑mi⋅j=2n⋅(n+1)×2m⋅(m+1)
可以 Θ ( 1 ) \Theta(1) Θ(1) 求解
不过这玩意要整除分块套整除分块,而且细节不少
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e7+7,mod=20101009;
int mu[N],sum[N];
vector<int> p;
bool bz[N];
int Sum(int x, int y)
{return ((x*(x+1)/2%mod)*(y*(y+1)/2%mod))%mod;
}
void init(int n)
{mu[1]=1;for(int i=2; i<=n; i++){if(!bz[i]){mu[i]=-1;p.push_back(i);}for(auto j:p){if(j*i>n) break;bz[i*j]=1;if(i%j==0) break;else mu[i*j]=-mu[i];}}for(int i=1; i<=n; i++) sum[i]=(sum[i-1]+mu[i]*i*i%mod)%mod;
}
int S(int n,int m)
{int ans=0;for(int l=1,r; l<=min(n,m); l=r+1){r=min(n/(n/l),m/(m/l));(ans+=Sum(n/l,m/l)%mod*(sum[r]-sum[l-1])%mod)%=mod;}return ans;
}
void O_o()
{int n,m,ans=0;cin>>n>>m;init(n);for(int l=1,r; l<=min(n,m); l=r+1){r=min(n/(n/l),m/(m/l));(ans+=((r-l+1)*(l+r)/2)%mod*S(n/l,m/l)%mod)%=mod;}cout<<(ans+mod)%mod;
}
signed main()
{ios::sync_with_stdio(false); cin.tie(0),cout.tie(0);int T=1;// cin>>T;while(T--){O_o();}
}