莫反练习题

呃,其实最重要的步骤就几个:

  1. 看到类似 \(\sum\limits_{i=1}^n\sum\limits_{j=1}^m\gcd(i,j)\) 这类计数就转化为枚举 \(\gcd(i,j)=k\),后面就是 \(k[\gcd(i,j)=k]\),目的是弄出来这个 \([\gcd(i,j)=k]\)

  2. 转化为 \([\gcd(i,j)=1]\)

  3. 转化为 \(\sum\limits_{d\mid \gcd(i,j)}\mu(d)\)

  4. 枚举 \(i,j\) 转化为枚举 \(d\)

  5. 如果外面还有一层,即内层为 \(\lfloor\dfrac{n}{pd}\rfloor\) 形式的,令 \(T=pd\),然后枚举 \(pd\) 以及 \(d\mid T\)

推导过程如果没有写 \(\min(n,m)\) 都默认 \(n<m\)

「HAOI2011」Problem b

前置:\([\gcd(i,j)=1]=\sum\limits_{d\mid \gcd(i,j)}\mu(d)\)

考虑容斥,设 \(f(l,r)\)\(x\in [1,l],y\in [1,r]\) 的答案。

\(ans=f(b,d)-f(a,d)-f(b,c)+f(a,c)\)

考虑如何求解 \(f\)

\[\sum\limits_{i=1}^n\sum\limits_{j=1}^m[\gcd(i,j)=k] \]

\[\sum\limits_{i=1}^n\sum\limits_{j=1}^m[\gcd(\frac{i}{k},\frac{j}{k})=1] \]

改为枚举 \(\frac{i}{k}\)\(\frac{j}{k}\)

\[\sum\limits_{i=1}^{\lfloor\dfrac{n}{k}\rfloor}\sum\limits_{j=1}^{\lfloor\dfrac{m}{k}\rfloor}[\gcd(i,j)=1] \]

\[\sum\limits_{i=1}^{\lfloor\dfrac{n}{k}\rfloor}\sum\limits_{j=1}^{\lfloor\dfrac{m}{k}\rfloor}\sum\limits_{d\mid \gcd(i,j)}\mu(d) \]

改为枚举 \(d\),范围显然是 \([1,\lfloor\dfrac{\min(n,m)}{k}\rfloor]\),相当于对于每个 \(d\),求有多少对 \(i,j\) 满足 \(d\mid \gcd(i,j)\),即 \(d\mid i\)\(d\mid j\)。显然,\([1,\lfloor\dfrac{n}{k}\rfloor]\) 范围内是 \(d\) 的倍数的数有 \(\lfloor\dfrac{n}{dk}\rfloor\) 个:

\[\sum\limits_{d=1}^{\lfloor\dfrac{\min(n,m)}{k}\rfloor}\mu(d)\lfloor\dfrac{n}{dk}\rfloor\lfloor\dfrac{m}{dk}\rfloor \]

数论分块即可。

#include<bits/stdc++.h>
#define sd std::
//#define int long long
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define f(i,a,b) for(int i=(a);i>=(b);i--)
#define MIN(x,y) (x<y?x:y)
#define MAX(x,y) (x>y?x:y)
#define me(x,y) memset(x,y,sizeof x)
#define pii sd pair<int,int>
#define X first
#define Y second
#define Fr(a) for(auto it:a)
int read(){int w=1,c=0;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) c=(c<<3)+(c<<1)+ch-48;return w*c;}
void printt(int x){if(x>9) printt(x/10);putchar(x%10+48);}
void print(int x){if(x<0) putchar('-'),printt(-x);else printt(x);}
void put(int x){print(x);putchar('\n');}
void printk(int x){print(x);putchar(' ');}
const int N=1e5+10;
sd vector<int> pr;
int p[N],mu[N],sum[N];
void pre(int n)
{
	mu[1]=1;p[1]=1;
	F(i,2,n)
	{
		if(!p[i]) pr.emplace_back(i),mu[i]=-1;
		Fr(pr)
		{
			if(it*i>n) break;
			p[i*it]=1;
			if(i%it==0)
			{
				mu[it*i]=0;
				break;
			}
			else mu[it*i]=-mu[i];
		}
	}
	F(i,1,n) sum[i]=sum[i-1]+mu[i];
}
int ask(int l,int r)
{
	return sum[r]-sum[l-1];
}
int query(int n,int m,int k)
{
	int ans=0;
	for(int l=1,r=0;l<=MIN(n,m);l=r+1)
	{
		r=MIN(m/(m/l),n/(n/l));
		ans+=ask(l,r)*(n/l/k)*(m/l/k);
	}
	return ans;
}
int n,a,b,c,d,k;
void solve()
{
	pre(50000);
	n=read();
	F(i,1,n)
	{
		a=read()-1,b=read(),c=read()-1,d=read(),k=read();
		int ans=query(b,d,k);
		ans-=query(a,d,k)+query(b,c,k)-query(a,c,k);
		put(ans);
	}
}
int main()
{
	int T=1;
//	T=read();
	while(T--) solve();
    return 0;
}

「SDOI2015」约数个数和

前置:

\[d(ij)=\sum\limits_{x\mid i}\sum\limits_{y\mid j}[\gcd(x,y)=1] \]

原式:

\[\sum_{i=1}^n\sum_{j=1}^md(ij) \]

\[\sum_{i=1}^n\sum_{j=1}^m\sum\limits_{x\mid i}\sum\limits_{y\mid j}[\gcd(x,y)=1] \]

改为枚举因子 \(x,y\)

\[\sum\limits_{x=1}^n\sum\limits_{y=1}^m\lfloor\frac{n}{x}\rfloor\lfloor\frac{m}{y}\rfloor[\gcd(x,y)=1] \]

\([\gcd(x,y)=1]\) 根据套路化去:

\[\sum\limits_{x=1}^n\sum\limits_{y=1}^m\lfloor\frac{n}{x}\rfloor\lfloor\frac{m}{y}\rfloor\sum\limits_{d\mid \gcd(x,y)}\mu(d) \]

枚举 \(d\)

\[\sum\limits_{d=1}^{\min(n,m)}\mu (d)\sum\limits_{d\mid x}\sum\limits_{d\mid y}\lfloor\frac{n}{x}\rfloor\lfloor\frac{m}{y}\rfloor \]

后面两个循环改为枚举 \(d\) 的倍数:

\[\sum\limits_{d=1}^{\min(n,m)}\mu (d)\sum\limits_{x=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{y=1}^{\lfloor\frac{m}{d}\rfloor}\lfloor\frac{n}{dx}\rfloor\lfloor\frac{m}{dy}\rfloor \]

\[\sum\limits_{d=1}^{\min(n,m)}\mu (d)(\sum\limits_{x=1}^{\lfloor\frac{n}{d}\rfloor}\lfloor\frac{n}{dx}\rfloor)(\sum\limits_{y=1}^{\lfloor\frac{m}{d}\rfloor}\lfloor\frac{m}{dy}\rfloor) \]

考虑预处理 \(f(x)=\sum\limits_{i=1}^x \lfloor\frac{x}{i}\rfloor\)。答案为 \(\sum\limits_{d=1}^{\min(n,m)}\mu (d)f(\lfloor\frac{n}{d}\rfloor)f(\lfloor\frac{m}{d}\rfloor)\)

数列分块即可。

#include<bits/stdc++.h>
#define sd std::
#define int long long
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define ff(i,a,b) for(int i=(a);i>=(b);i--)
#define MIN(x,y) (x<y?x:y)
#define MAX(x,y) (x>y?x:y)
#define me(x,y) memset(x,y,sizeof x)
#define pii sd pair<int,int>
#define X first
#define Y second
#define Fr(a) for(auto it:a)
int read(){int w=1,c=0;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) c=(c<<3)+(c<<1)+ch-48;return w*c;}
void printt(int x){if(x>9) printt(x/10);putchar(x%10+48);}
void print(int x){if(x<0) putchar('-'),printt(-x);else printt(x);}
void put(int x){print(x);putchar('\n');}
void printk(int x){print(x);putchar(' ');}
const int N=5e4+10;
sd vector<int> pr;
int p[N],mu[N],sum[N],f[N];
void pre(int n)
{
	mu[1]=1;
	F(i,2,n)
	{
		
		if(!p[i]) pr.emplace_back(i),mu[i]=-1;
		Fr(pr)
		{
			if(i*it>n) break;
			p[i*it]=1;
			if(i%it==0)
			{
				mu[i*it]=0;
				break;
			}
			mu[i*it]=-mu[i];
		}
	}
	F(i,1,n) sum[i]=sum[i-1]+mu[i];
	F(x,1,n)
	{
		for(int l=1,r=0;l<=x;l=r+1)
		{
			r=x/(x/l);
			f[x]+=(r-l+1)*(x/l);
		}
	}
}
void solve()
{
	int n=read(),m=read();
	if(n>m) sd swap(n,m);//默认n<=m
	int ans=0;
	for(int l=1,r=0;l<=n;l=r+1)
	{
		r=MIN(n/(n/l),m/(m/l));
		ans+=(sum[r]-sum[l-1])*f[n/l]*f[m/l];
	}
	put(ans);
}
signed main()
{
	pre(50000);
	int T=1;
	T=read();
	while(T--) solve();
    return 0;
}

「BZOJ2693」jzptab

弱化版:P1829。原题有多测。

\[\sum\limits_{i=1}^n\sum\limits_{j=1}^m \operatorname{lcm}(i,j) \]

\[\sum\limits_{i=1}^n \sum\limits_{j=1}^m \frac{ij}{\gcd(i,j)} \]

\[\sum\limits_{d=1}^{\min(n,m)}\sum\limits_{i=1}^n\sum\limits_{j=1}^m \frac{ij}{d}[\gcd(i,j)=d] \]

枚举 \(\lfloor\frac{n}{i}\rfloor\)\(\lfloor\frac{m}{i}\rfloor\)

\[\begin{array}{c} \sum\limits_{d=1}^{\min(n,m)}\sum\limits_{i=1}^{\lfloor \frac{n}{d} \rfloor }\sum\limits_{j=1}^{\lfloor \frac{m}{d} \rfloor } ijd[\gcd(i,j)=1] \end{array}\]

按套路化简

\[\begin{array}{c} \sum\limits_{d=1}^{n}d\sum\limits_{i=1}^{\lfloor \frac{n}{d} \rfloor }\sum\limits_{j=1}^{\lfloor \frac{m}{d} \rfloor } ij\sum\limits_{p\mid \gcd(i,j)}\mu(p) \end{array}\]

最外层循环 \(d\) 不变,枚举 \(p\)

\[\sum\limits_{d=1}^n d\sum\limits_{p=1}^{\lfloor\frac{n}{d}\rfloor} \mu(p)p^2\sum\limits_{i=1}^{\lfloor\frac{n}{dp}\rfloor}i\sum\limits_{j=1}^{\lfloor\frac{m}{dp}\rfloor}j \]

\(i,j\) 枚举的是 \(p\)\(i\) 倍和 \(j\) 倍)

\(f(x)=\sum\limits_{i=1}^x,k=dp\)

\[\sum\limits_{d=1}^nd\sum\limits_{p=1}^{\lfloor\frac{n}{d}\rfloor}\mu(p)p^2f(\lfloor\frac{n}{k}\rfloor)f(\lfloor\frac{m}{k}\rfloor) \]

考虑枚举 \(k\)

\[\sum\limits_{k=1}^n f(\lfloor\frac{n}{k}\rfloor)f(\lfloor\frac{m}{k}\rfloor)\sum\limits_{d\mid k}d\mu(\frac{k}{d})\frac{k^2}{d^2} \]

\[\sum\limits_{k=1}^n f(\lfloor\frac{n}{k}\rfloor)f(\lfloor\frac{m}{k}\rfloor)\sum\limits_{d\mid k}\mu(\frac{k}{d})\frac{k^2}{d} \]

枚举 \(d\) 改为枚举 \(p\)\(\frac{k}{d}\)):

\[\sum\limits_{k=1}^n f(\lfloor\frac{n}{k}\rfloor)f(\lfloor\frac{m}{k}\rfloor)k\sum\limits_{p\mid k}\mu(p)p \]

考虑 \(F(k)=\sum\limits_{p\mid k}\mu(p)p\),容易看出 \(F\) 是积性函数,可以线性筛筛出,最后数列分块即可。

#include<bits/stdc++.h>
#define sd std::
#define int long long
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define ff(i,a,b) for(int i=(a);i>=(b);i--)
#define MIN(x,y) (x<y?x:y)
#define MAX(x,y) (x>y?x:y)
#define me(x,y) memset(x,y,sizeof x)
#define pii sd pair<int,int>
#define X first
#define Y second
#define Fr(a) for(auto it:a)
int read(){int w=1,c=0;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) c=(c<<3)+(c<<1)+ch-48;return w*c;}
void printt(int x){if(x>9) printt(x/10);putchar(x%10+48);}
void print(int x){if(x<0) putchar('-'),printt(-x);else printt(x);}
void put(int x){print(x);putchar('\n');}
void printk(int x){print(x);putchar(' ');}
const int N=1e7+10,P=100000009;
sd vector<int> pr;
int p[N],g[N],sum[N];
void pre(int n)
{
	g[1]=1;
	F(i,2,n)
	{
		if(!p[i]) pr.emplace_back(i),g[i]=(P+1-i)%P;
		Fr(pr)
		{
			if(i*it>n) break;
			p[i*it]=1;
			if(i%it==0)
			{
				g[i*it]=g[i];
				break;
			}
			g[i*it]=g[i]*g[it]%P;
		}
	}
	F(i,1,n) sum[i]=(sum[i-1]+g[i]*i%P)%P;
}
int f(int k)
{
	return k*(k+1)/2;
}
int n,m;
void solve()
{
	n=read(),m=read();
	if(n>m) sd swap(n,m);
	int ans=0;
	for(int l=1,r=0;l<=n;l=r+1)
	{
		r=MIN(n/(n/l),m/(m/l));
		int k1=f(n/l)%P,k2=f(m/l)%P;
		(ans+=(sum[r]-sum[l-1]+P)%P*k1%P*k2%P)%=P;
	}
	put(ans);
}
signed main()
{
	pre(10000000);
	int T=1;
	T=read();
	while(T--) solve();
    return 0;
}

「SDOI2017」数字表格

即求 \(\prod\limits_{i=1}^n\prod\limits_{j=1}^mf_{\gcd(i,j)}\)\(f\) 是斐波那契数列。

化简式子。

\[\prod\limits_{k=1}^n \prod\limits_{i=1}^n\prod\limits_{j=1}^mf_{k}[\gcd(i,j)=k] \]

考虑对于每个 \(k\),求出 \(f_k\) 会乘多少次:

\[\prod\limits_{k=1}^n f_k^{\sum\limits_{i=1}^n\sum\limits_{j=1}^m[\gcd(i,j)=k]} \]

右上角指数是套路:

\[\sum\limits_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{k}\rfloor}[\gcd(i,j)=1] \]

\[\sum\limits_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{k}\rfloor}\sum\limits_{d\mid \gcd(i,j)}\mu(d) \]

\[\sum\limits_{d=1}^{\lfloor\frac{n}{k}\rfloor}\mu(d)\lfloor\frac{n}{kd}\rfloor\lfloor\frac{m}{kd}\rfloor \]

带回原式:

\[\prod\limits_{k=1}^n f_k^{\sum\limits_{d=1}^{\lfloor\frac{n}{k}\rfloor}\mu(d)\lfloor\frac{n}{kd}\rfloor\lfloor\frac{m}{kd}\rfloor} \]

然后令 \(T=kd\),枚举 \(T\)

\[\prod\limits_{T=1}^n(\prod\limits_{k\mid T} f_{k}^{\mu(\frac{T}{k})})^{\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor} \]

\(F(T)=\sum\limits_{k\mid T} f_{k}^{\mu(\frac{T}{k})}\),枚举倍数可以 \(O(n\log n)\) 求解 \(F\)

原式即 \(\prod\limits_{T=1}^nF(T)^{\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor}\),维护 \(F\) 前缀积,数列分块即可。

#include<bits/stdc++.h>
#define sd std::
#define int long long
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define ff(i,a,b) for(int i=(a);i>=(b);i--)
#define MIN(x,y) (x<y?x:y)
#define MAX(x,y) (x>y?x:y)
#define me(x,y) memset(x,y,sizeof x)
#define pii sd pair<int,int>
#define X first
#define Y second
#define Fr(a) for(auto it:a)
int read(){int w=1,c=0;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) c=(c<<3)+(c<<1)+ch-48;return w*c;}
void printt(int x){if(x>9) printt(x/10);putchar(x%10+48);}
void print(int x){if(x<0) putchar('-'),printt(-x);else printt(x);}
void put(int x){print(x);putchar('\n');}
void printk(int x){print(x);putchar(' ');}
const int N=1e6+10,P=1e9+7;
sd vector<int> pr;
int p[N],mu[N],f[N],g[N],FF[N];//g代表FF前缀积
int ksm(int a,int b)
{
	int res=1;
	while(b)
	{
		if(b&1) res=res*a%P;
		a=a*a%P;
		b>>=1;
	}
	return res;
}
int inv(int x)
{
	return ksm(x,P-2);
}
void pre(int n)
{
	mu[1]=1;
	F(i,2,n)
	{
		if(!p[i]) pr.emplace_back(i),mu[i]=-1;
		Fr(pr)
		{
			if(it*i>n) break;
			p[i*it]=1;
			if(i%it==0) break;
			mu[i*it]=-mu[i];
		}
	}
	f[1]=f[2]=1;
	F(i,3,n) f[i]=(f[i-1]+f[i-2])%P;
	F(i,1,n) FF[i]=1;
	F(i,1,n)
	{
		for(int j=1;i*j<=n;j++)
		{
			if(mu[j]>0) FF[i*j]=FF[i*j]*ksm(f[i],mu[j])%P;
			else FF[i*j]=FF[i*j]*inv(ksm(f[i],-mu[j]))%P;
		}
	}
	g[0]=1;
	F(i,1,n) g[i]=g[i-1]*FF[i]%P;
}
int n,m;
void solve()
{
	n=read(),m=read();
	if(n>m) sd swap(n,m);
	int ans=1;
	for(int l=1,r=0;l<=n;l=r+1)
	{
		r=MIN(n/(n/l),m/(m/l));
		(ans*=ksm((g[r]*inv(g[l-1]))%P,(n/l)*(m/l)))%=P;
	}
	put(ans);
}
signed main()
{
	pre(1000000);
	int T=1;
	T=read();
	while(T--) solve();
    return 0;
}

「BZOJ2820」YY的GCD

\(\sum\limits_{p\in \mathbb{Prime}}\sum\limits_{i=1}^n\sum\limits_{j=1}^m[\gcd(i,j)=p]\)

还是先考虑化简。

\[\sum\limits_{p\in \mathbb{Prime}}\sum\limits_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{p}\rfloor}\sum\limits_{d\mid \gcd(i,j)} \mu(d) \]

\[\sum\limits_{p\in \mathbb{Prime}}\sum\limits_{d=1}^{\lfloor\frac{n}{p}\rfloor}\mu(d)\lfloor\frac{n}{pd}\rfloor\lfloor\frac{m}{pd}\rfloor \]

考虑令 \(T=pd\),枚举 \(T\)

\[\sum\limits_{T=1}^n\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor\sum_{p\mid T,p\in \mathbb{Prime}}\mu(\frac{T}{p}) \]

考虑预处理 \(F(T)=\sum_{p\mid T,p\in \mathbb{Prime}}\mu(\frac{T}{p})\) 以及它的前缀和,对每个质数枚举倍数做到 \(O(m\log m)\) 是容易的,\(m\) 为质数数量。

然后数列分块即可。

#include<bits/stdc++.h>
#define sd std::
#define int long long
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define ff(i,a,b) for(int i=(a);i>=(b);i--)
#define MIN(x,y) (x<y?x:y)
#define MAX(x,y) (x>y?x:y)
#define me(x,y) memset(x,y,sizeof x)
#define pii sd pair<int,int>
#define X first
#define Y second
#define Fr(a) for(auto it:a)
int read(){int w=1,c=0;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) c=(c<<3)+(c<<1)+ch-48;return w*c;}
void printt(int x){if(x>9) printt(x/10);putchar(x%10+48);}
void print(int x){if(x<0) putchar('-'),printt(-x);else printt(x);}
void put(int x){print(x);putchar('\n');}
void printk(int x){print(x);putchar(' ');}
const int N=1e7+10;
sd vector<int> pr;
int p[N],mu[N],f[N];
void pre(int n)
{
	mu[1]=1;
	F(i,2,n)
	{
		if(!p[i]) pr.emplace_back(i),mu[i]=-1;
		Fr(pr)
		{
			if(i*it>n) break;
			p[i*it]=1;
			if(i%it==0) break;
			mu[i*it]=-mu[i];
		}
	}
	Fr(pr)
	{
		F(i,1,n/it)
		{
			if(i*it>n) break;
			f[i*it]+=mu[i];
		}
	}
	F(i,1,n) f[i]+=f[i-1];
}
int n,m;
void solve()
{
	n=read(),m=read();
	if(n>m) sd swap(n,m);
	int ans=0;
	for(int l=1,r=0;l<=n;l=r+1)
	{
		r=MIN(n/(n/l),m/(m/l));
		ans+=(f[r]-f[l-1])*(n/l)*(m/l);
	}
	put(ans);
}
signed main()
{
	pre(10000000);
	int T=1;
	T=read();
	while(T--) solve();
    return 0;
}

剩下的题都差不多,就不写过程了,留作练习。

「BZOJ4407」于神之怒加强版

#include<bits/stdc++.h>
#define sd std::
#define int long long
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define ff(i,a,b) for(int i=(a);i>=(b);i--)
#define MIN(x,y) (x<y?x:y)
#define MAX(x,y) (x>y?x:y)
#define me(x,y) memset(x,y,sizeof x)
#define pii sd pair<int,int>
#define X first
#define Y second
#define Fr(a) for(auto it:a)
int read(){int w=1,c=0;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) c=(c<<3)+(c<<1)+ch-48;return w*c;}
void printt(int x){if(x>9) printt(x/10);putchar(x%10+48);}
void print(int x){if(x<0) putchar('-'),printt(-x);else printt(x);}
void put(int x){print(x);putchar('\n');}
void printk(int x){print(x);putchar(' ');}
const int N=5e6+10,P=1e9+7;
int n,m,mu[N],idk[N];
sd vector<int> pr;
int p[N];
int ksm(int a,int b)
{
	int res=1;
	while(b)
	{
		if(b&1) res=res*a%P;
		a=a*a%P;
		b>>=1;
	}
	return res;
}
int f[N];
void pre(int n,int K)
{
	f[1]=1;
	F(i,2,n)
	{
		if(!p[i]) pr.emplace_back(i),f[i]=(ksm(i,K)-1+P)%P;
		Fr(pr)
		{
			if(i*it>n) break;
			p[i*it]=1;
			if(i%it==0)
			{
				f[i*it]=f[i]*ksm(it,K)%P;
				break;
			}
			f[i*it]=f[i]*f[it]%P;
		}
	}
	F(i,1,n) (f[i]+=f[i-1])%=P;
}
void solve()
{
	n=read(),m=read();
	if(n>m) sd swap(n,m);
	int ans=0;
	for(int l=1,r=0;l<=n;l=r+1)
	{
		r=MIN(n/(n/l),m/(m/l));
		(ans+=(f[r]-f[l-1]+P)*(n/l)%P*(m/l)%P)%=P;
	}
	put(ans);
}
signed main()
{
	int T=read(),K=read();
	pre(5000000,K);
	while(T--) solve();
    return 0;
}

GCD SUM

题目名字是我校OJ的,洛谷原题好像叫疯狂的gcd。

就是求 \(\sum\limits_{i=1}^n\sum\limits_{j=1}^n\gcd(i,n)\)

#include<bits/stdc++.h>
#define sd std::
#define int long long
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define ff(i,a,b) for(int i=(a);i>=(b);i--)
#define MIN(x,y) (x<y?x:y)
#define MAX(x,y) (x>y?x:y)
#define me(x,y) memset(x,y,sizeof x)
#define pii sd pair<int,int>
#define X first
#define Y second
#define Fr(a) for(auto it:a)
int read(){int w=1,c=0;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) c=(c<<3)+(c<<1)+ch-48;return w*c;}
void printt(int x){if(x>9) printt(x/10);putchar(x%10+48);}
void print(int x){if(x<0) putchar('-'),printt(-x);else printt(x);}
void put(int x){print(x);putchar('\n');}
void printk(int x){print(x);putchar(' ');}
const int N=1e5+10;
sd vector<int> pr;
int p[N],mu[N];
void pre(int n)
{
	mu[1]=1;
	F(i,2,n)
	{
		if(!p[i]) pr.emplace_back(i),mu[i]=-1;
		Fr(pr)
		{
			if(it*i>n) break;
			p[it*i]=1;
			if(i%it==0) break;
			mu[it*i]=-mu[i];
		}
	}
}
int n;
void solve()
{
	n=read();
	int ans=0;
	F(k,1,n) F(d,1,n/k)
	{
		ans+=k*mu[d]*(n/k/d)*(n/k/d);
	}
	put(ans);
}
signed main()
{
	pre(100000);
	int T=1;
	// T=read();
	while(T--) solve();
    return 0;
}

「NOI 2010」能量采集

#include<bits/stdc++.h>
#define sd std::
#define int long long
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define ff(i,a,b) for(int i=(a);i>=(b);i--)
#define MIN(x,y) (x<y?x:y)
#define MAX(x,y) (x>y?x:y)
#define me(x,y) memset(x,y,sizeof x)
#define pii sd pair<int,int>
#define X first
#define Y second
#define Fr(a) for(auto it:a)
int read(){int w=1,c=0;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) c=(c<<3)+(c<<1)+ch-48;return w*c;}
void printt(int x){if(x>9) printt(x/10);putchar(x%10+48);}
void print(int x){if(x<0) putchar('-'),printt(-x);else printt(x);}
void put(int x){print(x);putchar('\n');}
void printk(int x){print(x);putchar(' ');}
const int N=1e5+10;
sd vector<int> pr;
int p[N],mu[N];
void pre(int n)
{
	mu[1]=1;
	F(i,2,n)
	{
		if(!p[i]) pr.emplace_back(i),mu[i]=-1;
		Fr(pr)
		{
			if(it*i>n) break;
			p[it*i]=1;
			if(i%it==0) break;
			mu[it*i]=-mu[i];
		}
	}
}
int n,m;
void solve()
{
	n=read(),m=read();
	if(n>m) sd swap(n,m);
	int ans=0;
	F(k,1,n) F(d,1,n/k)
	{
		ans+=k*mu[d]*(n/k/d)*(m/k/d);
	}
	put(2*ans-n*m);
}
signed main()
{
	pre(100000);
	int T=1;
	// T=read();
	while(T--) solve();
    return 0;
}

https://www.luogu.com/article/998kttnc

https://www.cnblogs.com/linzhengmin/p/11060871.html

https://www.cnblogs.com/linzhengmin/p/10994520.html

https://www.cnblogs.com/linzhengmin/p/11046230.html

https://www.cnblogs.com/Zmonarch/p/14746546.html

posted @ 2025-02-07 10:28  _E_M_T  阅读(32)  评论(0)    收藏  举报