Luogu P4902 乘積

題目 咱們要求的是c++

\[ \prod\limits_{i=a}^b\prod\limits_{j=1}^i(\frac ij)^{\lfloor\frac ij\rfloor} \]

先把它拆開函數

\[ \prod\limits_{i=a}^b\prod\limits_{j=1}^ii^{\lfloor\frac ij\rfloor}(\frac1{\prod\limits_{i=a}^b\prod\limits_{j=1}^ij^{\lfloor\frac ij\rfloor}}) \]

對於右邊,咱們把$j\in[1,i]$換成$j\in[1,b]\(是沒有任何問題的。由於\)\forall j\in(i,b],\lfloor\frac ij\rfloor=0$,至關於多乘了幾個$1$。 而後再交換右邊的連乘符號spa

\[ \prod\limits_{i=a}^b\prod\limits_{j=1}^ii^{\lfloor\frac ij\rfloor}(\frac1{\prod\limits_{j=1}^b\prod\limits_{i=a}^bj^{\lfloor\frac ij\rfloor}}) \]

咱們把連乘換成指數的求和code

\[ \prod\limits_{i=a}^bi^{\sum\limits_{j=1}^i\lfloor\frac ij\rfloor}(\frac1{\prod\limits_{j=1}^bj^{\sum\limits_{i=a}^b\lfloor\frac ij\rfloor}}) \]

而後容斥一下get

\[ \prod\limits_{i=1}^bi^{\sum\limits_{j=1}^i\lfloor\frac ij\rfloor}\prod\limits_{j=1}^{a-1}j^{\sum\limits_{i=1}^{a-1}\lfloor\frac ij\rfloor}(\frac1{\prod\limits_{j=1}^bj^{\sum\limits_{i=1}^b\lfloor\frac ij\rfloor}\prod\limits_{i=1}^{a-1}i^{\sum\limits_{j=1}^i\lfloor\frac ij\rfloor}}) \]
\[ let\ a=a-1,f(n)=\prod\limits_{i=1}^ni^{\sum\limits_{j=1}^i\lfloor\frac ij\rfloor},g(n)=\prod\limits_{j=1}^nj^{\sum\limits_{i=1}^n\lfloor\frac ij\rfloor} \]

則要求的式子就變成了it

\[ f(b)g(a)(\frac1{f(a)g(b)}) \]

因此若是咱們可以以$O(nlog\ n)$的複雜的篩出$f,g$的話就能解決問題。 首先計算$f$class

\[ let\ \sigma(n)=\sum\limits_{d|n}1,d(n)=\sum\limits_{i=1}^n\sigma(i) \]

考慮到枚舉約數和枚舉倍數的等價性im

\[ d(n)=\sum\limits_{i=1}^n\lfloor\frac ni\rfloor \]

top

\[ f(n)=\prod\limits_{i=1}^ni^{d(i)} \]

顯然其遞推式爲di

\[ f(n)=f(n-1)n^{d(n)} \]

因此咱們能夠$O(nlog\ n)\(篩出\)\sigma$即除數函數,而後前綴和求出,\(d\),再按遞推式求出$f$。 注意$d$是做爲指數存在,因此取模時須要對$P-1$取模。 再計算$g$

\[ let\ t(n)=\frac{g(n)}{g(n-1)}=\prod\limits_{i=1}^ni^{\lfloor\frac ni\rfloor},h(n)=\frac{t(n)}{t(n-1)}=\prod\limits_{d|n}d \]

顯然咱們能夠$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;
}
相關文章
相關標籤/搜索