zoukankan      html  css  js  c++  java
  • 洛谷3704 [SDOI2017] 数字表格 【莫比乌斯反演】

    题目分析:

    比较有意思,但是套路的数学题。

    题目要求$ prod_{i=1}^{n} prod_{j=1}^{m}Fib(gcd(i,j)) $.

    注意到$ gcd(i,j) $有大量重复,采用莫比乌斯反演。可以写成:

    $ prod_{i=1}^{min(n,m)}Fib(i)^{sum_{i|d}mu(frac{d}{i})lfloor frac{n}{d} floorlfloor frac{m}{d} floor} $.

    更进一步的,我们可以发现幂是一个求和,那么把求和依次提出,再重新组合在一起,就变成了:

    $ prod_{i=1}^{min(n,m)}(prod_{i|d}Fib(i)^{mu(frac{d}{i})})^{lfloorfrac{n}{d} floorlfloorfrac{m}{d} floor} $.

    可以发现最外层的积的下标是$ i $或$ d $对答案没有影响,原因我们可以考虑当下标是$ i $的时候,它会对它的每个倍数产生影响,而倍数的影响是不论$ i $的。所以对于每个倍数我们同样可以枚举因数,式子可以写成:

    $ prod_{d=1}^{min(n,m)}(prod_{i|d}Fib(i)^{mu(frac{d}{i})})^{lfloorfrac{n}{d} floorlfloorfrac{m}{d} floor} $.

    注意这个式子,它的里层是一个只与当前的$ d $有关的式子,而外层是一个典型的分块。那么我们预处理出里面的情况并做前缀积,外面再采用分块,这道题就可以顺利解决。

    对于里面的式子,我们需要$ O(nlog{n}) $进行预处理,而每个询问我们可以分块解决,单次询问的时间复杂度是$ O(sqrt{n}log{n}) $所以时间复杂度是$O(nlog{n}+Tsqrt{n}log{n})$.

    注意到这题没有用到斐波那契数列的任何性质,所以函数$ Fib(x) $可以改成任意其它函数。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int mod = 1000000007;
     5 const int maxn = 1000005;
     6 
     7 const int N = 1000000;
     8 
     9 int n,m;
    10 int Fib[maxn],Inv[maxn];
    11 int MFib[maxn],MInv[maxn];
    12 
    13 int flag[maxn],prime[maxn>>3],mu[maxn],num;
    14 
    15 int fast_pow(int now,long long pw){
    16     int z = now,ans = 1;long long im = 1;
    17     while(im <= pw){
    18     if(im & pw) ans = (1ll*ans*z)%mod;
    19     z = (1ll*z*z)%mod; im <<= 1;
    20     }
    21     return ans;
    22 }
    23 
    24 void GetMiu(){
    25     flag[1] = 1;mu[1] = 1;
    26     for(int i=2;i<=N;i++){
    27     if(!flag[i]) prime[++num] = i,mu[i] = -1;
    28     for(int j=1;j<=num&&i*prime[j]<=N;j++){
    29         flag[i*prime[j]] = 1;
    30         if(i % prime[j] == 0) {mu[i*prime[j]] = 0;break;}
    31         else mu[i*prime[j]] = -mu[i];
    32     }
    33     }
    34 }
    35 
    36 void init(){
    37     GetMiu();
    38     Fib[0] = 0; Fib[1] = 1;
    39     for(int i=2;i<=N;i++) Fib[i] = (Fib[i-1]+Fib[i-2])%mod;
    40     for(int i=0;i<=N;i++) Inv[i] = fast_pow(Fib[i],mod-2);
    41     for(int i=0;i<=N;i++) MFib[i] = 1;
    42     for(int i=1;i<=N;i++){
    43     for(int j=1;i*j<=N;j++){
    44         if(mu[j] == 0) continue;
    45         if(mu[j] == 1) MFib[i*j] = (1ll*MFib[i*j]*Fib[i])%mod;
    46         else MFib[i*j] = (1ll*MFib[i*j]*Inv[i])%mod;
    47     }
    48     }
    49     for(int i=1;i<=N;i++) MFib[i] = (1ll*MFib[i]*MFib[i-1])%mod;
    50     for(int i=0;i<=N;i++) MInv[i] = fast_pow(MFib[i],mod-2);
    51 }
    52 
    53 void work(){
    54     int res = 1;
    55     for(int i=1;i<=min(n,m);){
    56     int nxt = min(n/(n/i),m/(m/i));
    57     long long z1 = 1ll*(n/i)*(m/i);
    58     res = (1ll*res*fast_pow((1ll*MFib[nxt]*MInv[i-1])%mod,z1))%mod;
    59     i = nxt+1;
    60     }
    61     printf("%d
    ",res);
    62 }
    63 
    64 int main(){
    65     init();
    66     int T; scanf("%d",&T);
    67     while(T--){
    68     scanf("%d%d",&n,&m);
    69     work();
    70     }
    71     return 0;
    72 }
  • 相关阅读:
    nignx的master进程和worker进程的作用
    JVM运行机制
    ElasticSearch介绍与安装
    Maven打可执行包的pom.xml配置
    pg按日,周,月进行数据统计
    数据库中重复数据查询和删除
    聚类算法的评估应面向具体问题
    将博客搬至CSDN
    Mutual Information
    层次化聚类
  • 原文地址:https://www.cnblogs.com/Menhera/p/9113609.html
Copyright © 2011-2022 走看看