luogu P3704 [SDOI2017]数字表格

传送门

我是真的弱,推式子只能推一半

下面假设(n<m)

考虑题目要求的东西,可以考虑每个gcd的贡献,即$$prod_{d=1}{n}f[d]{sum_{i=1}{lfloorfrac{n}{d} floor}sum_{j=1}{lfloorfrac{m}{d} floor}[gcd(i,j)=1]}$$

(n=sum_{d|n} mu[d]),得$$prod_{d=1}{n}f[d]{sum_{i=1}{lfloorfrac{n}{d} floor}sum_{j=1}{lfloorfrac{m}{d} floor}sum_{k|i,k|j}mu[k]}$$$$prod_{d=1}{n}f[d]{sum_{k=1}^{lfloorfrac{n}{d} floor}mu[k]lfloorfrac{n}{kd} floorlfloorfrac{m}{kd} floor}$$

大力数论分块即可获得60'好成绩

如果我们令(t=kd),然后把t提出来,即则$$prod_{t=1}{n}prod_{d|t}f[d]{lfloorfrac{n}{t} floorlfloorfrac{m}{t} floormu[lfloorfrac{n}{d} floor]}$$$$prod_{t=1}{n}(prod_{d|t}f[d]{mu[lfloorfrac{n}{d} floor]})^{lfloorfrac{n}{t} floorlfloorfrac{m}{t} floor}$$

里面的可以枚举每个数倍数预处理,然后就是数论分块

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define LL long long
#define ldb long double
#define il inline
#define re register

using namespace std;
const int N=1e6+10,mod=1e9+7;
il int rd()
{
  int x=0,w=1;char ch=0;
  while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
  while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
  return x*w;
}
il int fpow(int a,int b){int an=1;while(b){if(b&1) an=1ll*an*a%mod;a=1ll*a*a%mod,b>>=1;}return an;}
bool v[N];
int prm[N],mu[N],tt,fb[N],ifb[N],f[N],ivf[N];

int main()
{
  fb[0]=0,fb[1]=1,ifb[0]=ifb[1]=1;
  for(int i=2;i<=N-10;++i) fb[i]=(fb[i-1]+fb[i-2])%mod,ifb[i]=fpow(fb[i],mod-2);
  mu[1]=1;
  for(int i=2;i<=N-10;++i)
    {
      if(!v[i]) v[i]=1,prm[++tt]=i,mu[i]=-1;
      for(int j=1;j<=tt&&i*prm[j]<=N-10;++j)
        {
          v[i*prm[j]]=1,mu[i*prm[j]]=-mu[i];
          if(i%prm[j]==0) {mu[i*prm[j]]=0;break;}
        }
    }
  for(int i=0;i<=N-10;++i) f[i]=1;
  for(int i=1;i<=N-10;++i)
    for(int j=1;i*j<=N-10;++j)
      f[i*j]=1ll*f[i*j]*((~mu[j])?fpow(fb[i],mu[j]):ifb[i])%mod;
  ivf[0]=1;
  for(int i=1;i<=N-10;++i) f[i]=1ll*f[i]*f[i-1]%mod,ivf[i]=fpow(f[i],mod-2);
  int T=rd();
  while(T--)
    {
      int n=rd(),m=rd(),ans=1;
      if(n>m) swap(n,m);
      for(int i=1,j;i<=n;i=j+1)
        {
          j=min(n/(n/i),m/(m/i));
          ans=1ll*ans*fpow(1ll*f[j]*ivf[i-1]%mod,1ll*(m/i)*(n/i)%(mod-1))%mod;
        }
      printf("%d
",ans);
    }
  return 0;
}
原文地址:https://www.cnblogs.com/smyjr/p/10152912.html