• 解题:SDOI 2017 数字表格


    题面

    反演题,推式子么=。=

    $prodlimits_{d=1}^{min(n,m)}prodlimits_{i=1}^nprodlimits_{j=1}^m[gcd(i,j)==d]fib[d]$

    把$fib[d]$前提,前面的连乘就跑到指数上去了

    $prodlimits_{d=1}^{min(n,m)}fib[d]^{sumlimits_{i=1}^nsumlimits_{j=1}^m[gcd(i,j)==d]}$

    开始反演那坨指数,等等这玩意不是做过么=。=

    $sumlimits_{i=1}^nsumlimits_{j=1}^m[gcd(i,j)==d]$

    $sumlimits_{i=1}^{leftlfloorfrac{n}{d} ight floor}sumlimits_{j=1}^{leftlfloorfrac{m}{d} ight floor}[gcd(i,j)==1]$

    $sumlimits_{i=1}^{min(leftlfloorfrac{n}{d} ight floor,leftlfloorfrac{m}{d} ight floor)}μ(i)leftlfloorfrac{n}{id} ight floorleftlfloorfrac{m}{id} ight floor$

    于是把$id$捉出来,在原来的整个式子里枚举$id$(不是那个$id$,都懂)

    $prodlimits_{k=1}^{min(n,m)}(prodlimits_{d|k}fib[d]^{μ(frac{k}{d})})^{leftlfloorfrac{n}{k} ight floorleftlfloorfrac{m}{k} ight floor}$

    停,可以做了

    对于$prodlimits_{d|k}fib[d]^{μ(frac{k}{d})}$,预处理,大力把每个数乘到倍数上去,复杂度$O(nlog n)$

    对于$leftlfloorfrac{n}{k} ight floorleftlfloorfrac{m}{k} ight floor$这个指数,可以数论分块,这样再加个快速幂每次回答复杂度就是$O(sqrt nlog mod)$了,可能有点卡常?我倒是一次过了

     1 #include<cstdio>
     2 #include<cstring> 
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=1000005,M=1000000,mod=1e9+7;
     6 int fib[N],ifb[N],pfb[N],ipf[N];
     7 int pri[N],npr[N],mul[N];
     8 int T,n,m,x,y,mn,cnt,ans;
     9 int qpow(int x,int k)
    10 {
    11     if(k==1) return x;
    12     int tmp=qpow(x,k/2);
    13     return k%2?1ll*tmp*tmp%mod*x%mod:1ll*tmp*tmp%mod;
    14 }
    15 void exGCD(int a,int b,int &x,int &y)
    16 {
    17     if(!b) {x=1,y=0; return ;} 
    18     exGCD(b,a%b,y,x); y-=a/b*x;
    19 }
    20 int Inv(int b)
    21 {
    22     exGCD(b,mod,x,y);
    23     return (x+mod)%mod;
    24 }
    25 void prework()
    26 {
    27     register int i,j;
    28     npr[1]=true,mul[1]=1,fib[1]=1,ifb[1]=1,pfb[1]=1;
    29     for(i=2;i<=M;i++)
    30     {
    31         fib[i]=(fib[i-1]+fib[i-2])%mod;
    32         ifb[i]=Inv(fib[i]),pfb[i]=1;
    33         if(!npr[i])     
    34             pri[++cnt]=i,mul[i]=-1;
    35         for(j=1;j<=cnt&&i*pri[j]<=M;j++)
    36         {
    37             npr[i*pri[j]]=true;
    38             if(i%pri[j]==0) break;
    39             else mul[i*pri[j]]=-mul[i];
    40         }
    41     }
    42     for(i=1;i<=M;i++)
    43         for(j=i;j<=M;j+=i)
    44             if(mul[j/i]) pfb[j]=1ll*pfb[j]*((~mul[j/i])?fib[i]:ifb[i])%mod;
    45     pfb[0]=ipf[0]=1;
    46     for(i=1;i<=M;i++)
    47     {
    48         ipf[i]=Inv(pfb[i]);
    49         pfb[i]=1ll*pfb[i-1]*pfb[i]%mod;
    50         ipf[i]=1ll*ipf[i-1]*ipf[i]%mod;
    51     }
    52 }
    53 int main()
    54 {
    55     register int i,j;
    56     scanf("%d",&T),prework();
    57     while(T--)
    58     {
    59         scanf("%d%d",&n,&m);
    60         mn=min(n,m),ans=1;
    61         for(i=1;i<=mn;i=j+1)
    62         {
    63             j=min(n/(n/i),m/(m/i));
    64             ans=1ll*ans*qpow(1ll*pfb[j]*ipf[i-1]%mod,1ll*(n/i)*(m/i)%(mod-1))%mod;
    65         }
    66         printf("%d
    ",ans);
    67     }
    68     return 0;
    69 }
    View Code
  • 相关阅读:
    ARTS 计划第四周
    ARTS 计划第三周周
    计划表的科学设定
    C/C++内存分配
    ARTS 计划第二周周
    jsoncpp 和 libcurl的编译与使用 vs2010
    ARTS 计划第一周
    unix中的v节点和i节点
    百度地图demo
    带有定位当前位置的百度地图web api 前端代码
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/10148379.html
Copyright © 2020-2023  润新知