莫比乌斯反演
莫比乌斯反演
前置数论分块
感觉全是板子。
以下默认 \(n<m\)
-
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})\) 处理部分以外的部分定义为莫反板子,简称莫板。
你马上就会知道这样定义的好处。
-
数表
先不考虑 \(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'); }
-
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'); } }
-
约数个数和
首先有逆天结论:
\[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'); } }
-
数字表格
直接莫板,\(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'); } }
-
于神之怒加强版
枚举 \(\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'); } }
-
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'); } }
-
一个人的数论
莫板,发现有 \(\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); }
本文来自博客园,作者:xrlong,转载请注明原文链接:https://www.cnblogs.com/xrlong/articles/18197866