莫比乌斯反演

莫比乌斯反演

前置数论分块

感觉全是板子。

以下默认 \(n<m\)

  1. YY的GCD

    翻译: 求

    \[\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)\in prime] \]

    枚举 \(\gcd\)

    \[\sum_{p\in prime}\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=p] \]

    改上标

    \[\sum_{p\in prime}\sum_{i=1}^{\left\lfloor\frac{n}{p}\right\rfloor}\sum_{j=1}^{\left\lfloor\frac{m}{p}\right\rfloor}[\gcd(i,j)=1] \]

    莫反

    \[\sum_{p\in prime}\sum_{i=1}^{\left\lfloor\frac{n}{p}\right\rfloor}\sum_{j=1}^{\left\lfloor\frac{m}{p}\right\rfloor}\sum_{d\mid i}\sum_{d\mid j}\mu(d) \]

    枚举 \(d\)

    \[\sum_{p\in prime}\sum_{d=1}\mu(d)\sum_{i=1}^{\left\lfloor\frac{n}{pd}\right\rfloor}\sum_{j=1}^{\left\lfloor\frac{m}{pd}\right\rfloor} \]

    枚举 \(T=pd\)

    \[\sum_{T=1}^{n}\sum_{p|T\land p\in prime}\mu(\frac{T}{p})\left\lfloor\frac{n}{pd}\right\rfloor\left\lfloor\frac{m}{pd}\right\rfloor \]

    \(f(T)=\sum\limits_{p|T\land p\in prime}\mu(\frac{T}{p})\) 可以暴力调和级数处理,也可以考虑性质在线性筛时处理。

    \(\mu\) 有好性质,所以考虑 \(\mu\) 不为 \(0\) 时的可能,一是 \(T\) 的质因子幂次为一,二是在 \(p\) 时恰好消掉唯一二次。

    \(T\) 的最小质因子为 \(p'\)

    \(p\mid T\), 因为在 \(p\not=p'\)\(\mu\)\(0\),所以 \(f(T)=\mu(\frac{T}{p'})\)

    \(p\nmid T\), 当 \(p=p'\)\(\mu\)\(\mu(\frac{T}{p'})\),当 \(p\not=p'\) 时为 \(\mu(\frac{T}{p})=\mu(p')\mu(\frac{T}{pp'})\),前面的是 \(-1\),后面的是 \(f(\frac{T}{p'})\),所以 \(f(T)=\mu(\frac{T}{p'})-f(\frac{T}{p'})\)

    最后数论分块即可。

    CODE
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long llt;
    typedef unsigned long long ull;
    #define int llt
    const int N=1e7+3;
    #define For(i,a,b,c) for(register int $L=a,$R=b,$C=c,$D=(0<=$C)-($C<0),i=$L;i*$D<=$R*$D;i+=$C)
    int t;
    
    namespace IO{
    	template<typename T> inline void write(T x){
    		static T st[45];T top=0;if(x<0)x=~x+1,putchar('-');
    		do{st[top++]=x%10;}while(x/=10);while(top)putchar(st[--top]^48);
    	}
    	template<typename T> inline void read(T &x){
    		char s=getchar();x=0;bool pd=false;while(s<'0'||'9'<s){if(s=='-') pd=true;s=getchar();}
    		while('0'<=s&&s<='9')x=(x<<1)+(x<<3)+(s^48),s=getchar();if(pd) x=-x;
    	}
    }
    namespace IO{
    	template<typename T,typename... Args> inline void read(T& x,Args&... args){read(x);read(args...);}
    	inline void write(const char c){putchar(c);}
    	inline void write(const char *c){int len=strlen(c);For(i,0,len-1,1) putchar(c[i]);}
    	template<typename T> inline void Write(T x){write(x);putchar(' ');}
    	inline void Write(const char c){write(c);if(c!='\n') putchar(' ');}
    	inline void Write(const char *c){write(c);if(c[strlen(c)-1]!='\n') putchar(' ');}
    	template<typename T,typename... Args> inline void write(T x,Args... args){write(x);write(args...);}
    	template<typename T,typename... Args> inline void Write(T x,Args... args){Write(x);Write(args...);}
    }
    using namespace IO;
    class MATH{
    private:
    	vector<int> pri; int mu[N],qf[N]; bool ntp[N];
    public:
    	MATH(){
    		mu[1]=1;
    		For(i,2,N-1,1){
    			if(!ntp[i]) pri.push_back(i),mu[i]=-1,qf[i]=1;
    			for(int j:pri){
    				if(j*i>=N) break;
    				ntp[i*j]=1,mu[i*j]=-mu[i],qf[i*j]=-qf[i]+mu[i];
    				if(i%j==0){mu[i*j]=0,qf[i*j]=mu[i];break;}
    			}
    			qf[i]+=qf[i-1];
    		}
    	}
    	inline llt solve(int n,int m){
    		llt ans=0;
    		for(register int l=1,r;l<=min(n,m);l=r+1){
    			r=min(n/(n/l),m/(m/l));
    			ans+=1ll*(qf[r]-qf[l-1])*(n/l)*(m/l);
    		}
    		return ans;
    	}
    }mth;
    
    signed main(){
    #ifndef ONLINE_JUDGE
    	freopen("in_out/in.in","r",stdin);
    	freopen("in_out/out.out","w",stdout);
    #endif
    	read(t);
    	while(t--){
    		int n,m;read(n,m);
    		write(mth.solve(n,m),'\n');
    	}
    }
    

我们将上一个题除了最后的 \(f(T)=\sum\limits_{p|T\land p\in prime}\mu(\frac{T}{p})\) 处理部分以外的部分定义为莫反板子,简称莫板

你马上就会知道这样定义的好处。

  1. 数表

    先不考虑 \(a\) 的限制,套莫板

    处理 \(\sum\limits_{d\mid T}f(d)\mu(\frac Qd)\),这是狄利克雷卷积形式,是积性函数,直接筛。

    考虑 \(a\)

    离线将 \(a\) 排序,依次插入树状数组求前缀和,数论分块即可。

    CODE
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long llt;
    typedef unsigned long long ull;
    const int N=1e5+3,Q=2e4+3;
    #define For(i,a,b,c) for(register int $L=a,$R=b,$C=c,$D=(0<=$C)-($C<0),i=$L;i*$D<=$R*$D;i+=$C)
    int q;
    struct Question{int n,m,a,id,ans;}cq[Q];
    namespace IO{
    	template<typename T> inline void write(T x){
    		static T st[45];T top=0;if(x<0)x=~x+1,putchar('-');
    		do{st[top++]=x%10;}while(x/=10);while(top)putchar(st[--top]^48);
    	}
    	template<typename T> inline void read(T &x){
    		char s=getchar();x=0;bool pd=false;while(s<'0'||'9'<s){if(s=='-') pd=true;s=getchar();}
    		while('0'<=s&&s<='9')x=(x<<1)+(x<<3)+(s^48),s=getchar();if(pd) x=-x;
    	}
    }
    namespace IO{
    	template<typename T,typename... Args> inline void read(T& x,Args&... args){read(x);read(args...);}
    	inline void write(const char c){putchar(c);}
    	inline void write(const char *c){int len=strlen(c);For(i,0,len-1,1) putchar(c[i]);}
    	template<typename T> inline void Write(T x){write(x);putchar(' ');}
    	inline void Write(const char c){write(c);if(c!='\n') putchar(' ');}
    	inline void Write(const char *c){write(c);if(c[strlen(c)-1]!='\n') putchar(' ');}
    	template<typename T,typename... Args> inline void write(T x,Args... args){write(x);write(args...);}
    	template<typename T,typename... Args> inline void Write(T x,Args... args){Write(x);Write(args...);}
    }
    using namespace IO;
    inline bool cmp_a(Question a,Question b){return a.a<b.a;}
    inline bool cmp_id(Question a,Question b){return a.id<b.id;}
    class BIT{
    private: int sum[N<<2],tot_=1;
    public:
    	inline int lowbit(int x){return x&(-x);}
    	inline void add(int x,int t){while(x<N) sum[x]+=t,x+=lowbit(x);}
    	inline int get(int x){int ans=0;while(x>0) ans+=sum[x],x-=lowbit(x);return ans;}
    }bt;
    class MATH{
    private:
    	vector<int> pri; int mu[N],tsg_; bool ntp[N];
    	struct Sigma{
    		int t,id;
    		bool operator<(const Sigma x)const{return this->t<x.t;}
    	}sg[N];
    public:
    	MATH(){
    		mu[1]=1,sg[1]={1,1};tsg_=0;
    		For(i,2,N-1,1){
    			if(!ntp[i]) pri.push_back(i),mu[i]=-1,sg[i]={i+1,i};
    			for(int j:pri){
    				if(j*i>=N) break;
    				if(i%j==0){ntp[i*j]=1,mu[i*j]=0,sg[i*j]={(j+1)*sg[i].t-j*sg[i/j].t,i*j};break;}
    				else ntp[i*j]=1,mu[i*j]=-mu[i],sg[i*j]={sg[i].t*(j+1),i*j};
    			}
    		}
    		sort(sg+1,sg+N);
    	}
    	inline int solve(int n,int m,int a){
    		while(tsg_<N&&sg[tsg_+1].t<=a){
    			tsg_++;
    			For(i,1,(N-1)/sg[tsg_].id,1) 
    				bt.add(i*sg[tsg_].id,sg[tsg_].t*mu[i]);
    		}
    		int ans=0;
    		for(int l=1,r;l<=min(n,m);l=r+1){
    			r=min(n/(n/l),m/(m/l));
    			ans+=(n/r)*(m/r)*(bt.get(r)-bt.get(l-1));
    		}
    		return (ans&(~(1<<31)));
    	}
    }mth;
    
    signed main(){
    #ifndef ONLINE_JUDGE
    	freopen("in_out/in.in","r",stdin);
    	freopen("in_out/out.out","w",stdout);
    #endif
    	read(q);
    	For(i,1,q,1) read(cq[i].n,cq[i].m,cq[i].a),cq[i].id=i;
    	sort(cq+1,cq+1+q,cmp_a);
    	For(i,1,q,1) cq[i].ans=mth.solve(cq[i].n,cq[i].m,cq[i].a);
    	sort(cq+1,cq+1+q,cmp_id);
    	For(i,1,q,1) write(cq[i].ans,'\n');
    }
    
  2. DZY Loves Math

    莫板

    处理 \(g(T)=\sum\limits_{d\mid T}f(d)\mu(\frac Td)\)

    其实调和级数好像可以卡过

    依然考虑 \(\mu\) 性质,为了让其不为 \(0\)\(T,d\) 唯一分解后指数最多差 \(1\)

    \(T\) 分解后指数为 \(a_i\)\(d\)\(b_i\)

    \(\exists a_i<a_j\)\(b_i\) 一定不会是唯一最大的。

    所以当 \(\exists a_i\not=a_j\) 时,\(d\) 如何取都无所谓,而这时取到顶(\(b_i=a_i\))和不取到顶(\(b_i=a_i-1\))正好互为相反数,所以为 \(g(T)=0\)

    \(\forall a_i=a_j\),其他都可以像上面一样消掉,只有都不取到顶(\(\forall b_i=a_i-1\))消的时候会有剩余,此时 \(g(T)=(-1)^{a+1}\)

    CODE
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long llt;
    typedef unsigned long long ull;
    const int N=1e7+3,Q=1e4+3;
    #define For(i,a,b,c) for(register int $L=a,$R=b,$C=c,$D=(0<=$C)-($C<0),i=$L;i*$D<=$R*$D;i+=$C)
    int q;
    namespace IO{
    	template<typename T> inline void write(T x){
    		static T st[45];T top=0;if(x<0)x=~x+1,putchar('-');
    		do{st[top++]=x%10;}while(x/=10);while(top)putchar(st[--top]^48);
    	}
    	template<typename T> inline void read(T &x){
    		char s=getchar();x=0;bool pd=false;while(s<'0'||'9'<s){if(s=='-') pd=true;s=getchar();}
    		while('0'<=s&&s<='9')x=(x<<1)+(x<<3)+(s^48),s=getchar();if(pd) x=-x;
    	}
    }
    namespace IO{
    	template<typename T,typename... Args> inline void read(T& x,Args&... args){read(x);read(args...);}
    	inline void write(const char c){putchar(c);}
    	inline void write(const char *c){int len=strlen(c);For(i,0,len-1,1) putchar(c[i]);}
    	template<typename T> inline void Write(T x){write(x);putchar(' ');}
    	inline void Write(const char c){write(c);if(c!='\n') putchar(' ');}
    	inline void Write(const char *c){write(c);if(c[strlen(c)-1]!='\n') putchar(' ');}
    	template<typename T,typename... Args> inline void write(T x,Args... args){write(x);write(args...);}
    	template<typename T,typename... Args> inline void Write(T x,Args... args){Write(x);Write(args...);}
    }
    using namespace IO;
    class MATH{
    private:
    	vector<int> pri;int g[N]; bool ntp[N];
    public:
    	MATH(){
    		int cnt[N],val[N];
    		For(i,2,N-1,1){
    			if(!ntp[i]) pri.push_back(i),g[i]=cnt[i]=val[i]=1;
    			for(int j:pri){
    				if(j*i>=N) break;
    				ntp[i*j]=1;
    				if(!(i%j)){
    					cnt[i*j]=cnt[i]+1,val[i*j]=val[i];
    					if(val[i]==1) g[i*j]=1;
    					else g[i*j]=(cnt[i*j]==cnt[val[i]]?-g[val[i]]:0);
    					break;
    				}else
    					cnt[i*j]=1,val[i*j]=i,g[i*j]=(cnt[i]==1?-g[i]:0);
    			}
    		}
    		For(i,1,N-1,1) g[i]+=g[i-1];
    	}
    	inline llt solve(int a,int b){
    		llt ans=0;
    		for(int l=1,r;l<=min(a,b);l=r+1){
    			r=min(a/(a/l),b/(b/l));
    			ans+=1ll*(g[r]-g[l-1])*(a/l)*(b/l);
    		}
    		return ans;
    	}
    }mth;
    
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("in_out/in.in","r",stdin);
    	freopen("in_out/out.out","w",stdout);
    #endif
    	read(q);
    	while(q--){
    		int a,b;read(a,b);
    		write(mth.solve(a,b),'\n');
    	}
    }
    
  3. 约数个数和

    首先有逆天结论:

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

    然后转而枚举 \(x,y\)莫板后数论分块即可(其实可以不转而枚举 \(kd\)

    CODE
    #include<bits/stdc++.h>
    #include<sys/mman.h>
    #include<fcntl.h>
    using namespace std;
    using llt=long long;
    using llf=long double;
    using ull=unsigned long long;
    #define Ct const
    #define Il __always_inline
    #define For(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
    #define For_(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
    #define For_it(i,a,b) for(auto i=(a);i!=(b);++i)
    #define int long long
    
    namespace IO{
    #ifdef ONLINE_JUDGE
    	int Fin=fileno(stdin); FILE* Fout=stdout;
    #elif defined(UN_FAST)
    	FILE *Fin=freopen("in_out/in.in","r",stdin),*Fout=freopen("in_out/out.out","w",stdout);
    #else
    	int Fin=open("in_out/in.in",0); FILE *Fout=freopen("in_out/out.out","w",stdout);
    #endif // file
    #ifdef UN_FAST
    	char cc;
    	#define G (cc=getchar())
    	#define C cc
    #else
    	const char *I=(char*)mmap(0,1<<28,1,2,Fin,0)-1; 
    	#define G (*++I)
    	#define C (*I)
    #endif // fast (mmap)
    #define P(x) putc_unlocked(x,Fout)
    	template<class T> Il void read(T &x){x=0;bool f=0; while(f|=G==45,C<48); while(x=x*10+(C&15),G>47); f?x=-x:0;}
    	template<class T> void write(T x){if(x<0) P('-'),x=-x; if(x/10) write(x/10); P('0'+x%10);}
    	Il void read(char &c){while(G<33); c=C;} void read(char *s){char *p=s-1; while(G<33); while(*++p=C,G>32); *++p='\0';}
    	Il void read(string &s){s.clear(); while(G<33); while(s.push_back(C),G>32);}
    	template<class T=int> Il T read(){T a; return read(a),a;}
    	template<class T,class ...Argc> Il void read(T &x,Argc &...argc){read(x),read(argc...);}
    	Il void write(const char &c){P(c);} Il void write(const char *s){for(const char *c=s;*c!='\0';++c) P(*c);}
    	Il void write(const string &s){for(const char &c:s) P(c);}
    	template<class T,class ...Argc> Il void write(const T &x,const Argc &...argc){write(x),write(argc...);}
    	template<class T> Il void Write(const T &x){write(x),P(' ');} Il void Write(const char &c){P(c); if(c>32) P(' ');}
    	template<class T,class ...Argc> Il void Write(const T &x,const Argc &...argc){Write(x),Write(argc...);}
    #undef G
    #undef C
    #undef P
    }using IO::read; using IO::write; using IO::Write;
    
    constexpr int N=5e4+3;
    int t;
    
    namespace MT{
    	vector<int> pri; bool ntp[N];
    	int qmu[N],qd[N];
    	struct INIT{INIT(){
    		int cnt[N]={0};
    		qmu[1]=qd[1]=ntp[1]=1;
    		For(i,2,N-3,1){
    			if(!ntp[i]) pri.push_back(i),qmu[i]=-1,cnt[i]=1,qd[i]=2;
    			for(Ct int &p:pri){
    				if(i*p>=N) break;
    				ntp[i*p]=1;
    				if(i%p) qmu[i*p]=-qmu[i],cnt[i*p]=1,qd[i*p]=qd[i]*2;
    				else{qmu[i*p]=0,cnt[i*p]=cnt[i]+1,qd[i*p]=qd[i]/cnt[i*p]*(cnt[i*p]+1); break;}
    			}
    			qmu[i]+=qmu[i-1],qd[i]+=qd[i-1];
    		}
    	}}Initer;
    	Il int Mu(Ct int &l,Ct int &r){return qmu[r]-qmu[l-1];}
    	Il int D(Ct int &r){return qd[r];}
    }
    
    signed main(){
    	read(t);
    	while(t--){
    		int n,m,len,ans=0; read(n,m); len=min(n,m);
    		for(int l=1,r;l<=len;l=r+1){
    			r=min(n/(n/l),m/(m/l));
    			ans+=MT::Mu(l,r)*MT::D(n/l)*MT::D(m/l);
    		}
    		write(ans,'\n');
    	}
    }
    
  4. 数字表格

    直接莫板\(O(n\log n)\) 调和级数处理,数论分块即可。

    CODE
    #include<bits/stdc++.h>
    #include<sys/mman.h>
    #include<fcntl.h>
    using namespace std;
    using llt=long long;
    using llf=long double;
    using ull=unsigned long long;
    #define Ct const
    #define Il __always_inline
    #define For(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
    #define For_(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
    #define For_it(i,a,b) for(auto i=(a);i!=(b);++i)
    
    namespace IO{
    #ifdef ONLINE_JUDGE
    	int Fin=fileno(stdin); FILE* Fout=stdout;
    #elif defined(UN_FAST)
    	FILE *Fin=freopen("in_out/in.in","r",stdin),*Fout=freopen("in_out/out.out","w",stdout);
    #else
    	int Fin=open("in_out/in.in",0); FILE *Fout=freopen("in_out/out.out","w",stdout);
    #endif // file
    #ifdef UN_FAST
    	char cc;
    	#define G (cc=getchar())
    	#define C cc
    #else
    	const char *I=(char*)mmap(0,1<<28,1,2,Fin,0)-1; 
    	#define G (*++I)
    	#define C (*I)
    #endif // fast (mmap)
    #define P(x) putc_unlocked(x,Fout)
    	template<class T> Il void read(T &x){x=0;bool f=0; while(f|=G==45,C<48); while(x=x*10+(C&15),G>47); f?x=-x:0;}
    	template<class T> void write(T x){if(x<0) P('-'),x=-x; if(x/10) write(x/10); P('0'+x%10);}
    	Il void read(char &c){while(G<33); c=C;} void read(char *s){char *p=s-1; while(G<33); while(*++p=C,G>32); *++p='\0';}
    	Il void read(string &s){s.clear(); while(G<33); while(s.push_back(C),G>32);}
    	template<class T=int> Il T read(){T a; return read(a),a;}
    	template<class T,class ...Argc> Il void read(T &x,Argc &...argc){read(x),read(argc...);}
    	Il void write(const char &c){P(c);} Il void write(const char *s){for(const char *c=s;*c!='\0';++c) P(*c);}
    	Il void write(const string &s){for(const char &c:s) P(c);}
    	template<class T,class ...Argc> Il void write(const T &x,const Argc &...argc){write(x),write(argc...);}
    	template<class T> Il void Write(const T &x){write(x),P(' ');} Il void Write(const char &c){P(c); if(c>32) P(' ');}
    	template<class T,class ...Argc> Il void Write(const T &x,const Argc &...argc){Write(x),Write(argc...);}
    #undef G
    #undef C
    #undef P
    }using IO::read; using IO::write; using IO::Write;
    
    constexpr int N=1e6+3,MOD=1e9+7;
    int t;
    
    namespace MT{
    	int f[N],ivf[N];
    	int Fpw(int a,int b){
    		int ans=1;
    		while(b){
    			if(b&1) ans=1ll*ans*a%MOD;
    			a=1ll*a*a%MOD,b>>=1;
    		}
    		return ans;
    	}
    	int Inv(Ct int &a){return Fpw(a,MOD-2);}
    	struct INIT{INIT(){
    		vector<int> pri; bool ntp[N]={0};
    		int fib[N]={0},mu[N]={0};
    		fib[1]=mu[1]=ntp[1]=1;
    		For(i,2,N-3,1){
    			if(!ntp[i]) pri.push_back(i),mu[i]=-1;
    			for(Ct int &p:pri){
    				if(i*p>=N) break;
    				ntp[i*p]=1;
    				if(i%p) mu[i*p]=-mu[i];
    				else{mu[i*p]=0; break;}
    			}
    			fib[i]=(fib[i-1]+fib[i-2])%MOD;
    		}
    		int inv[N]; For(i,1,N-3,1) inv[i]=Inv(fib[i]);
    		auto P=[&fib,&inv,&mu](Ct int &i,Ct int &j){return !mu[j]?1:(mu[j]>0?fib[i]:inv[i]);};
    		fill(f,f+N-2,1),ivf[0]=1;
    		For(k,1,N-3,1) For(t,k,N-3,k) f[t]=1ll*f[t]*P(k,t/k)%MOD;
    		For(i,1,N-3,1) f[i]=1ll*f[i-1]*f[i]%MOD,ivf[i]=Inv(f[i]);
    	}}Initer;
    	Il int F(Ct int &l,Ct int &r){return 1ll*f[r]*ivf[l-1]%MOD;}
    }
    
    signed main(){
    	read(t);
    	while(t--){
    		int n,m,ans=1; read(n,m);
    		if(n>m) swap(n,m);
    		for(int l=1,r;l<=n;l=r+1){
    			r=min(n/(n/l),m/(m/l));
    			ans=1ll*ans*MT::Fpw(MT::F(l,r),1ll*(n/l)*(m/l)%(MOD-1))%MOD;
    		}
    		write(ans,'\n');
    	}
    }
    
  5. 于神之怒加强版

    枚举 \(\gcd\) 转化成:

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

    莫板后是积性函数,直接筛(这才是真正板子吧)。

    CODE
    #include<bits/stdc++.h>
    #include<sys/mman.h>
    #include<fcntl.h>
    using namespace std;
    using llt=long long;
    using llf=long double;
    using ull=unsigned long long;
    #define Ct const
    #define Il __always_inline
    #define For(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
    #define For_(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
    #define For_it(i,a,b) for(auto i=(a);i!=(b);++i)
    
    namespace IO{
    #ifdef ONLINE_JUDGE
    	int Fin=fileno(stdin); FILE* Fout=stdout;
    #elif defined(UN_FAST)
    	FILE *Fin=freopen("in_out/in.in","r",stdin),*Fout=freopen("in_out/out.out","w",stdout);
    #else
    	int Fin=open("in_out/in.in",0); FILE *Fout=freopen("in_out/out.out","w",stdout);
    #endif // file
    #ifdef UN_FAST
    	char cc;
    	#define G (cc=getchar())
    	#define C cc
    #else
    	const char *I=(char*)mmap(0,1<<28,1,2,Fin,0)-1; 
    	#define G (*++I)
    	#define C (*I)
    #endif // fast (mmap)
    #define P(x) putc_unlocked(x,Fout)
    	template<class T> Il void read(T &x){x=0;bool f=0; while(f|=G==45,C<48); while(x=x*10+(C&15),G>47); f?x=-x:0;}
    	template<class T> void write(T x){if(x<0) P('-'),x=-x; if(x/10) write(x/10); P('0'+x%10);}
    	Il void read(char &c){while(G<33); c=C;} void read(char *s){char *p=s-1; while(G<33); while(*++p=C,G>32); *++p='\0';}
    	Il void read(string &s){s.clear(); while(G<33); while(s.push_back(C),G>32);}
    	template<class T=int> Il T read(){T a; return read(a),a;}
    	template<class T,class ...Argc> Il void read(T &x,Argc &...argc){read(x),read(argc...);}
    	Il void write(const char &c){P(c);} Il void write(const char *s){for(const char *c=s;*c!='\0';++c) P(*c);}
    	Il void write(const string &s){for(const char &c:s) P(c);}
    	template<class T,class ...Argc> Il void write(const T &x,const Argc &...argc){write(x),write(argc...);}
    	template<class T> Il void Write(const T &x){write(x),P(' ');} Il void Write(const char &c){P(c); if(c>32) P(' ');}
    	template<class T,class ...Argc> Il void Write(const T &x,const Argc &...argc){Write(x),Write(argc...);}
    #undef G
    #undef C
    #undef P
    }using IO::read; using IO::write; using IO::Write;
    
    constexpr int N=5e6+3,MOD=1e9+7;
    
    int f[N],t,k;
    
    Il int Fpw(int a,int b){
    	int ans=1;
    	while(b){
    		if(b&1) ans=1ll*ans*a%MOD;
    		b>>=1,a=1ll*a*a%MOD;
    	}
    	return ans;
    }
    
    Il void Init(){
    	vector<int> pri; bool ntp[N]; pri.reserve(N);
    	int tmp[N]={0},inv[N]={0}; f[1]=1;
    	auto Inv=[&inv](Ct int &a){if(!inv[a]) inv[a]=Fpw(f[a],MOD-2); return inv[a];};
    	For(i,2,N-3,1){
    		if(!ntp[i]) pri.push_back(i),f[i]=Fpw(i,k)-1,tmp[i]=i;
    		for(Ct int &p:pri){
    			if(i*p>=N) break;
    			ntp[i*p]=1;
    			if(i%p) f[i*p]=1ll*f[i]*f[p]%MOD,tmp[i*p]=p;
    			else{
    				if((tmp[i*p]=tmp[i]*p)==i*p) f[i*p]=(Fpw(i*p,k)-Fpw(i,k)+MOD)%MOD;
    				else f[i*p]=1ll*f[i]*f[tmp[i*p]]%MOD*Inv(tmp[i])%MOD;
    				break;
    			}
    		}
    	}
    	For(i,1,N-3,1) f[i]=(f[i-1]+f[i])%MOD;
    }
    Il int F(Ct int &l,Ct int &r){return (f[r]-f[l-1]+MOD)%MOD;}
    
    int main(){
    	read(t,k),Init();
    	while(t--){
    		int n,m,ans=0; read(n,m);
    		if(n>m) swap(n,m);
    		for(int l=1,r;l<=n;l=r+1){
    			r=min(n/(n/l),m/(m/l));
    			ans=(ans+1ll*F(l,r)*(n/l)%MOD*(m/l)%MOD)%MOD;
    		}
    		write(ans,'\n');
    	}
    }
    
  6. jzptab

    简单结论:

    \[\operatorname{lcm}(a,b)=\frac{ab}{\gcd(a,b)} \]

    枚举,莫板,线性筛。

    CODE
    #include<bits/stdc++.h>
    #include<sys/mman.h>
    #include<fcntl.h>
    using namespace std;
    using llt=long long;
    using llf=long double;
    using ull=unsigned long long;
    #define Ct const
    #define Il __always_inline
    #define For(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
    #define For_(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
    #define For_it(i,a,b) for(auto i=(a);i!=(b);++i)
    #define int long long
    
    namespace IO{
    #ifdef ONLINE_JUDGE
    	int Fin=fileno(stdin); FILE* Fout=stdout;
    #elif defined(UN_FAST)
    	FILE *Fin=freopen("in_out/in.in","r",stdin),*Fout=freopen("in_out/out.out","w",stdout);
    #else
    	int Fin=open("in_out/in.in",0); FILE *Fout=freopen("in_out/out.out","w",stdout);
    #endif // file
    #ifdef UN_FAST
    	char cc;
    	#define G (cc=getchar())
    	#define C cc
    #else
    	const char *I=(char*)mmap(0,1<<28,1,2,Fin,0)-1; 
    	#define G (*++I)
    	#define C (*I)
    #endif // fast (mmap)
    #define P(x) putc_unlocked(x,Fout)
    	template<class T> Il void read(T &x){x=0;bool f=0; while(f|=G==45,C<48); while(x=x*10+(C&15),G>47); f?x=-x:0;}
    	template<class T> void write(T x){if(x<0) P('-'),x=-x; if(x/10) write(x/10); P('0'+x%10);}
    	Il void read(char &c){while(G<33); c=C;} void read(char *s){char *p=s-1; while(G<33); while(*++p=C,G>32); *++p='\0';}
    	Il void read(string &s){s.clear(); while(G<33); while(s.push_back(C),G>32);}
    	template<class T=int> Il T read(){T a; return read(a),a;}
    	template<class T,class ...Argc> Il void read(T &x,Argc &...argc){read(x),read(argc...);}
    	Il void write(const char &c){P(c);} Il void write(const char *s){for(const char *c=s;*c!='\0';++c) P(*c);}
    	Il void write(const string &s){for(const char &c:s) P(c);}
    	template<class T,class ...Argc> Il void write(const T &x,const Argc &...argc){write(x),write(argc...);}
    	template<class T> Il void Write(const T &x){write(x),P(' ');} Il void Write(const char &c){P(c); if(c>32) P(' ');}
    	template<class T,class ...Argc> Il void Write(const T &x,const Argc &...argc){Write(x),Write(argc...);}
    #undef G
    #undef C
    #undef P
    }using IO::read; using IO::write; using IO::Write;
    
    constexpr int N=1e7+3,MOD=1e8+9;
    namespace MT{
    	int f[N];
    	struct INIT{INIT(){
    		vector<int> pri; bool ntp[N]={0};
    		pri.reserve(N); f[1]=1;
    		For(i,2,N-3,1){
    			if(!ntp[i]) pri.emplace_back(i),f[i]=1-i;
    			for(Ct int &p:pri){
    				if(i*p>=N) break;
    				ntp[i*p]=1;
    				if(i%p) f[i*p]=1ll*f[i]*(1-p)%MOD;
    				else{f[i*p]=f[i]; break;}
    			}
    			f[i]=((1ll*f[i]*i%MOD+f[i-1])%MOD+MOD)%MOD;
    		}
    	}}Initer;
    	Il int F(Ct int &l,Ct int &r){return ((f[r]-f[l-1])%MOD+MOD)%MOD;}
    	Il int Sum(Ct int &r){return 1ll*r*(r+1)/2%MOD;}
    }
    
    int t;
    
    signed main(){
    	read(t);
    	while(t--){
    		int n,m,ans=0; read(n,m); if(n>m) swap(n,m);
    		for(int l=1,r;l<=n;l=r+1){
    			r=min(n/(n/l),m/(m/l));
    			ans=(ans+1ll*MT::Sum(n/l)*MT::Sum(m/l)%MOD*MT::F(l,r)%MOD)%MOD;
    		}
    		write(ans,'\n');
    	}
    }
    
  7. 一个人的数论

    莫板,发现有 \(\sum\limits_{i=1}^{k}i^d\),直接拉插,换成 \(\sum\limits_{i=1}^{d+1} a_i*k^i\) 后继续推。

    最后剩下的是积性函数,对于每个 \(p\) 暴力即可。

    CODE
    #include<bits/stdc++.h>
    #include<sys/mman.h>
    #include<fcntl.h>
    using namespace std;
    using llt=long long;
    using llf=long double;
    using ull=unsigned long long;
    #define Ct const
    #define Il __always_inline
    #define For(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
    #define For_(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
    #define For_it(i,a,b) for(auto i=(a);i!=(b);++i)
    
    namespace IO{
    #ifdef ONLINE_JUDGE
    	int Fin=fileno(stdin); FILE* Fout=stdout;
    #elif defined(UN_FAST)
    	FILE *Fin=freopen("in_out/in.in","r",stdin),*Fout=freopen("in_out/out.out","w",stdout);
    #else
    	int Fin=open("in_out/in.in",0); FILE *Fout=freopen("in_out/out.out","w",stdout);
    #endif // file
    #ifdef UN_FAST
    	char cc;
    	#define G (cc=getchar())
    	#define C cc
    #else
    	const char *I=(char*)mmap(0,1<<28,1,2,Fin,0)-1; 
    	#define G (*++I)
    	#define C (*I)
    #endif // fast (mmap)
    #define P(x) putc_unlocked(x,Fout)
    	template<class T> Il void read(T &x){x=0;bool f=0; while(f|=G==45,C<48); while(x=x*10+(C&15),G>47); f?x=-x:0;}
    	template<class T> void write(T x){if(x<0) P('-'),x=-x; if(x/10) write(x/10); P('0'+x%10);}
    	Il void read(char &c){while(G<33); c=C;} void read(char *s){char *p=s-1; while(G<33); while(*++p=C,G>32); *++p='\0';}
    	Il void read(string &s){s.clear(); while(G<33); while(s.push_back(C),G>32);}
    	template<class T=int> Il T read(){T a; return read(a),a;}
    	template<class T,class ...Argc> Il void read(T &x,Argc &...argc){read(x),read(argc...);}
    	Il void write(const char &c){P(c);} Il void write(const char *s){for(const char *c=s;*c!='\0';++c) P(*c);}
    	Il void write(const string &s){for(const char &c:s) P(c);}
    	template<class T,class ...Argc> Il void write(const T &x,const Argc &...argc){write(x),write(argc...);}
    	template<class T> Il void Write(const T &x){write(x),P(' ');} Il void Write(const char &c){P(c); if(c>32) P(' ');}
    	template<class T,class ...Argc> Il void Write(const T &x,const Argc &...argc){Write(x),Write(argc...);}
    #undef G
    #undef C
    #undef P
    }using IO::read; using IO::write; using IO::Write;
    
    constexpr int W=1003,D=103,MOD=1e9+7;
    int d,w,n,ans,cp[W],ca[W];
    vector<int> ck;
    
    namespace MT{
    	Il int Fpw(int a,int b){
    		int ans=1;
    		while(b){
    			if(b&1) ans=1ll*ans*a%MOD;
    			a=1ll*a*a%MOD,b>>=1;
    		}
    		return ans;
    	}
    	Il int Inv(Ct int &a){return Fpw(a,MOD-2);}
    	class LGG{
    	private:
    		int cy[D];
    		vector<int> tmp,mul;
    	public:
    		LGG(){tmp.reserve(D),mul.reserve(D);}
    		Il void Gety(){For(i,1,d+2,1) cy[i]=(cy[i-1]+Fpw(i,d))%MOD;}
    		Il void operator()(vector<int> &f){
    			int len=d+2;
    			f.clear(),f.resize(len),tmp.clear(),mul.clear(),mul.emplace_back(1);
    			For(i,1,len,1){
    				tmp.emplace_back(0); for(Ct int &k:mul) tmp.emplace_back(k);
    				For(j,0,i-1,1) tmp[j]=(tmp[j]-1ll*mul[j]*i%MOD+MOD)%MOD;
    				swap(tmp,mul),tmp.clear();
    			}
    			For(i,1,len,1){
    				int fd=1; tmp.clear(),tmp.resize(len);
    				For_(j,len,2,1) tmp[j-1]=(tmp[j-1]+mul[j])%MOD,tmp[j-2]=(tmp[j-2]+1ll*tmp[j-1]*i%MOD)%MOD;
    				tmp[0]=(tmp[0]+mul[1])%MOD;
    				For(j,1,len,1) if(i^j) fd=1ll*fd*(i-j)%MOD;
    				fd=1ll*Inv((fd+MOD)%MOD)*cy[i]%MOD;
    				For(j,0,len-1,1) f[j]=(f[j]+1ll*tmp[j]*fd%MOD)%MOD;
    			}
    		}
    	}Lgg;
    }
    
    int main(){
    	read(d,w); n=1;
    	For(i,1,w,1) read(cp[i],ca[i]),n=1ll*n*MT::Fpw(cp[i],ca[i])%MOD;
    	MT::Lgg.Gety(); MT::Lgg(ck);
    	For(i,1,d+1,1){
    		int tmp=1ll*ck[i]*MT::Fpw(n,i)%MOD;
    		For(j,1,w,1) tmp=1ll*tmp*(1-MT::Fpw(cp[j],(d-i+MOD-1)%(MOD-1)))%MOD;
    		ans=(ans+tmp)%MOD;
    	}
    	write((ans+MOD)%MOD);
    }
    
posted @ 2024-05-17 15:27  xrlong  阅读(9)  评论(0编辑  收藏  举报