莫比乌斯反演

莫比乌斯反演

前置数论分块

感觉全是板子。

以下默认 n<m

  1. YY的GCD

    翻译: 求

    i=1nj=1m[gcd(i,j)prime]

    枚举 gcd

    pprimei=1nj=1m[gcd(i,j)=p]

    改上标

    pprimei=1npj=1mp[gcd(i,j)=1]

    莫反

    pprimei=1npj=1mpdidjμ(d)

    枚举 d

    pprimed=1μ(d)i=1npdj=1mpd

    枚举 T=pd

    T=1np|Tpprimeμ(Tp)npdmpd

    f(T)=p|Tpprimeμ(Tp) 可以暴力调和级数处理,也可以考虑性质在线性筛时处理。

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

    T 的最小质因子为 p

    pT, 因为在 ppμ0,所以 f(T)=μ(Tp)

    pT, 当 p=pμμ(Tp),当 pp 时为 μ(Tp)=μ(p)μ(Tpp),前面的是 1,后面的是 f(Tp),所以 f(T)=μ(Tp)f(Tp)

    最后数论分块即可。

    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)=p|Tpprimeμ(Tp) 处理部分以外的部分定义为莫反板子,简称莫板

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

  1. 数表

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

    处理 dTf(d)μ(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)=dTf(d)μ(Td)

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

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

    T 分解后指数为 aidbi

    ai<ajbi 一定不会是唯一最大的。

    所以当 aiaj 时,d 如何取都无所谓,而这时取到顶(bi=ai)和不取到顶(bi=ai1)正好互为相反数,所以为 g(T)=0

    ai=aj,其他都可以像上面一样消掉,只有都不取到顶(bi=ai1)消的时候会有剩余,此时 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)=xiyj[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(nlogn) 调和级数处理,数论分块即可。

    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 转化成:

    i=1nj=1md=1ndk[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

    简单结论:

    lcm(a,b)=abgcd(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. 一个人的数论

    莫板,发现有 i=1kid,直接拉插,换成 i=1d+1aiki 后继续推。

    最后剩下的是积性函数,对于每个 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 @   5k_sync_closer  阅读(16)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示