[SDOI2017]数字表格
Link
Description
对于斐波那契 \(F\)。\(T\) 次询问,每次给定 \(n\) 和 \(m\) ,求
\[\prod_{i=1}^n \prod_{j=1}^m F_{gcd(i,j)}
\]
Solution
一开始就很蠢地把 \(F_{gcd(i,j)}\) 拆成 \(gcd(F_{i},F_{j})\)。虽然确实有这个结论,但是显然推不下去,而又没有考虑回溯……服了
其实不拆的话相当好推,就常规套路就行了。令 \(c=min(n,m)\)
\[\begin{align}
(*)=\prod_{d=1}^c F_d^{\sum_{i=1}^n \sum_{j=1}^m [gcd(i,j)=d]}
\end{align}
\]
然后立即发现右上角是一个熟悉得不能再熟悉的式子,直接跳过中间步骤,得到
\[\begin{align}
(1)&=\prod_{d=1}^c F_d^{\sum_{k=1}^{\lfloor \frac{n}{d} \rfloor} \mu(k)\lfloor \frac{n}{kd} \rfloor\lfloor \frac{m}{kd} \rfloor} \\
&=\prod_{T=1}^c \prod_{d|T} F_d^{\mu(\frac{T}{d})\lfloor \frac{n}{T} \rfloor\lfloor \frac{m}{T} \rfloor} \\
&=\prod_{T=1}^c \Big(\prod_{d|T} F_d^{\mu(\frac{T}{d})} \Big)^{\lfloor \frac{n}{T} \rfloor\lfloor \frac{m}{T} \rfloor}
\end{align}
\]
随便处理一下,复杂度 \(O(T\sqrt n\log n+n \log n)\),但好像我的跑得很慢?
#include<stdio.h>
#define Mod p
#define ll long long
#define N 1000007
inline int read(){
int x=0,flag=1; char c=getchar();
while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
return flag? x:-x;
}
int p=(1e9)+7;
ll qpow(ll x,ll y){
ll ret=1,cnt=0;
while(y>=(1ll<<cnt)){
if(y&(1ll<<cnt)) ret=ret*x%p;
x=x*x%p,cnt++;
}
return ret;
}
ll f[N][3],g[N];
int mu[N],P[N],cnt=0;
bool mk[N];
inline int min(int x,int y){return x<y? x:y;}
int main(){
f[0][2]=0,f[1][2]=1;
for(int i=2;i<N;i++) f[i][2]=(f[i-1][2]+f[i-2][2])%Mod;
for(int i=0;i<N;i++) f[i][0]=qpow(f[i][2],p-2);
mu[1]=1;
for(int i=2;i<N;i++){
if(!mk[i])
P[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&P[j]*i<N;j++){
mk[i*P[j]]=1;
if(i%P[j]) mu[i*P[j]]=-mu[i];
else break;
}
}
for(int i=0;i<N;i++) g[i]=f[i][1]=1;
for(int i=1;i<N;i++)
for(int j=1;j*i<N;j++)
g[i*j]=g[i*j]*f[i][mu[j]+1]%Mod;
for(int i=2;i<N;i++) g[i]=g[i]*g[i-1]%Mod;
int T=read();
while(T--){
int n=read(),m=read();
int rg=min(n,m);
ll ans=1;
for(int l=1,r;l<=rg;l=r+1){
r=min(n/(n/l),m/(m/l));
ans=ans*qpow(g[r]*qpow(g[l-1],p-2)%p,1ll*(n/l)*(m/l))%p;
}
printf("%lld\n",ans);
}
}