题目 咱们要求的是c++
先把它拆开函数
对于右边,咱们把$j\in[1,i]$换成$j\in[1,b]\(是没有任何问题的。由于\)\forall j\in(i,b],\lfloor\frac ij\rfloor=0$,至关于多乘了几个$1$。 而后再交换右边的连乘符号spa
咱们把连乘换成指数的求和code
而后容斥一下get
则要求的式子就变成了it
因此若是咱们可以以$O(nlog\ n)$的复杂的筛出$f,g$的话就能解决问题。 首先计算$f$class
考虑到枚举约数和枚举倍数的等价性im
则top
显然其递推式为di
因此咱们能够$O(nlog\ n)\(筛出\)\sigma$即除数函数,而后前缀和求出,\(d\),再按递推式求出$f$。 注意$d$是做为指数存在,因此取模时须要对$P-1$取模。 再计算$g$
显然咱们能够$O(nlog\ n)$筛出$h$即约数积函数,而后作两遍前缀积就能够获得$g$。
#include<bits/stdc++.h> using namespace std; namespace IO { char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[15],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21); char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);} void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;} void Put(char x){*oS++=x;if(oS==oT)Flush();} int read(){int x=0;char ch=Get();while(ch>57||ch<48)ch=Get();while(ch>=48&&ch<=57)x=x*10+(ch^48),ch=Get();return x;} void write(int x){int top=0;if(!x)Put('0');while(x)st[++top]=(x%10)+48,x/=10;while(top)Put(st[top--]);Put('\n');} } using namespace IO; const int N=1000007,A=1000000,P=993244853; int inc(int a,int b,int p=P){a+=b;return a>=p? a-p:a;} int mul(int a,int b){return 1ll*a*b%P;} int power(int a,int k){int r=1;for(;k;k>>=1,a=mul(a,a))if(k&1)r=mul(a,r);return r;} int d[N],s[N],f[N]; int main() { int i,j,n,a,b; s[0]=f[0]=1; for(i=1;i<=A;++i) s[i]=1; for(i=1;i<=A;++i) for(j=i;j<=A;j+=i) ++d[j],s[j]=mul(s[j],i); for(i=1;i<=A;++i) d[i]=inc(d[i],d[i-1],P-1),f[i]=mul(f[i-1],power(i,d[i])),s[i]=mul(s[i],s[i-1]); for(i=1;i<=A;++i) s[i]=mul(s[i],s[i-1]); for(n=read();n;--n) a=read()-1,b=read(),write(mul(mul(mul(power(f[a],P-2),f[b]),power(s[b],P-2)),s[a])); return Flush(),0; }