zoukankan      html  css  js  c++  java
  • 「专题总结」莫比乌斯反演2

    重做了一遍莫比乌斯反演1之后,手感不错,于是顺着2做下来。

    专题里混进来了一个杜教筛题看了半天没有明白。。。等等我就去学,先放着。。。

    记一下思路吧。

    无特别强调时,除法依旧表示向下取整。

    GuGuFishtion:

    $Description:$

    Today XianYu is too busy with his homework, but the boring GuGu is still disturbing him!!!!!!
    At the break time, an evil idea arises in XianYu's mind.
    ‘Come on, you xxxxxxx little guy.’
    ‘I will give you a function $phi(x)$ which counts the positive integers up to x that are relatively prime to x.’
    ‘And now I give you a fishtion, which named GuGu Fishtion, in memory of a great guy named XianYu and a disturbing and pitiful guy GuGu who will be cooked without solving my problem in 5 hours.’
    ‘The given fishtion is defined as follow:
    $Gu(a,b)=frac{phi(ab)}{phi(a)phi(b)}$
    And now you, the xxxxxxx little guy, have to solve the problem below given m,n,p.’
    $sumlimits_{a=1}^{m} sumlimits_{b=1}^{n} Gu(a,b) (mod p)$
    So SMART and KINDHEARTED you are, so could you please help GuGu to solve this problem?
    ‘GU GU!’ GuGu thanks.$T le 3,1 le n,m le 10^6,p le 10^9+7$

    考虑$phi$函数的求法:$phi(x) = prod (p-1)p^{k-1}$

    然后所说的$Gu$函数对每一个质因子考虑,如果$a,b$中有一个含有某质因子$p$则贡献为$1$,否则贡献为$frac{p-1}{p}$。

    所以其实只与$gcd$含有哪些种类的质因子有关,设其总贡献为$f(x)$。这个可以线筛出来。

    $sumlimits_{i=1}^{n} sumlimits_{j=1}^{m} f(gcd(i,j))$

    $=sumlimits_{p} f(p) sumlimits_{i=1}^{frac{n}{p}} sumlimits_{j=1}^{frac{m}{p}} [gcd(i,j)]$

    $=sumlimits_{p} f(p) sumlimits_{d} mu(d) frac{n}{pd} frac{m}{pd}$

    $=sumlimits_{x} frac{n}{x} frac{m}{x} sumlimits_{d} f(d) mu(frac{x}{d})$

    后一个和式$O(n ln n)$预处理一下就可以数论分块了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define S 1000005
     4 int mod,n,m,p[S],pc,f[S],ans,mu[S],g[S],iv[S];char np[S];
     5 int pow(int b,int t,int a=1){for(;t;t>>=1,b=1ll*b*b%mod)if(t&1)a=1ll*a*b%mod;return a;}
     6 int main(){
     7     int t;cin>>t;while(t--){
     8         cin>>n>>m>>mod;if(n>m)n^=m^=n^=m;pc=ans=0;f[1]=mu[1]=1;
     9         for(int i=1;i<=n;++i)g[i]=0;
    10         for(int i=2;i<=n;++i){
    11             if(!np[i])p[++pc]=i,f[i]=1ll*i*(iv[i]=pow(i-1,mod-2))%mod,mu[i]=-1;
    12             for(int j=1,x;j<=pc&&(x=p[j]*i)<=n;++j)
    13                 if(i%p[j])np[x]=1,f[x]=1ll*f[i]*p[j]%mod*iv[p[j]]%mod,mu[x]=-mu[i];
    14                 else{np[x]=1;f[x]=f[i];mu[x]=0;break;}
    15         }for(int i=1;i<=n;++i)for(int j=i;j<=n;j+=i)g[j]=(0ll+g[j]+mu[i]*f[j/i]+mod)%mod;
    16         for(int i=2;i<=n;++i)g[i]=(g[i]+g[i-1])%mod;
    17         for(int i=1,l,N,M;N=n/i,M=m/i,i<=n;i=l+1)l=min(n/N,m/M),ans=(ans+(g[l]-g[i-1]+0ll+mod)*N%mod*M)%mod;
    18         cout<<ans<<endl;
    19     }
    20 }
    View Code

    hdu6363 bookshelf:

    $Description:$

    Patrick Star bought a bookshelf, he named it ZYG !!
    Patrick Star has N book .
    The ZYG has K layers (count from 1 to K) and there is no limit on the capacity of each layer !
    Now Patrick want to put all N books on ZYG :
    1. Assume that the i-th layer has cnti($0 le cnt_i le N$) books finally.
    2. Assume that f[i] is the i-th fibonacci number (f[0]=0,f[1]=1,f[2]=1,f[i]=f[i−2]+f[i−1]).
    3. Define the stable value of i-th layers $stable_i=f[cnt_i]$.
    4. Define the beauty value of i-th layers $beauty_i=2^{stable_i}−1$.
    5. Define the whole beauty value of ZYG score=gcd(beauty1,beauty2,...,beautyk)(Note: gcd(0,x)=x).
    Patrick Star wants to know the expected value of score if Patrick choose a distribute method randomly !

    $n,k le 10^6,mod=10^9+7$

    题意是:$sumlimits_{cnt_i} gcd(2^{f[cnt_i]}-1) [sumlimits_{i=1}^{k} cnt_i = n]$

    首先对于$2$的若干次幂$-1$的$gcd$,肯定不能直接硬算。

    设$a geq b$则$gcd(2^a-1,2^b-1)=gcd((2^b-1) imes 2^{a-b} -1,2^b-1)=gcd(2^b-1,2^{a-b}-1)$

    然后就可以辗转相除得到$gcd(2^a-1,2^b-1)=2^{gcd(a,b)}-1$

    原式化简为$sumlimits_{cnt_i} (2^{gcd(f[cnt_i])}-1) [sumlimits_{i=1}^{k} cnt_i =n]$

    然后现在的问题在于$f[x]$的$gcd$,然而考虑斐波那契数列的生成,是辗转相加也就是更相减损的逆过程。

    简单一些的是:$gcd(f[x],f[x-1])=gcd(f[x-1]+f[x-2],f[x-1])=gcd(f[x-1],f[x-2])$。

    同理有$gcd(f[x],f[y])=gcd(f[y],f[x-y])$。依旧可以辗转相除得到$gcd(f[x],f[y])=f[gcd(x,y)]$

    代入原式得到:$sumlimits_{cnt_i} (2^{f[gcd(cnt_i)]}-1) [sumlimits_{i=1}^{k} cnt_i =n]$

    $=sumlimits_{p} (2^{f[p]} -1) sumlimits_{cnt_i=1}^{frac{n}{p}} [gcd(cnt_i)] [sumlimits_{i=1}^{k} cnt_i imes p=n] $

    $=sumlimits_{p} (2^{f[p]} -1) sumlimits_{d} mu(d) sumlimits_{cnt_i=1}^{frac{n}{pd}} [cnt_i imes p imes d =n]$

    $=sumlimits_{x|n} (sumlimits_{cnt_i=1}^{frac{n}{x}} [sumlimits_{i=1}^{k} cnt_i imes x = n] ) sumlimits_{p|x} mu(frac{p}{x}) (2^{f[p]}-1)$

    后面的是个$O(n ln n)$的预处理。前面用挡板法算一个组合数。枚举$x$回答询问。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define mod 1000000007
     4 #define S 1000005
     5 int pow(int b,int t,int a=1){for(;t;t>>=1,b=1ll*b*b%mod)if(t&1)a=1ll*a*b%mod;return a;}
     6 int fac[S<<1],inv[S<<1],n,k,t,g[S],f[S],p[S],mu[S],pc;char np[S];
     7 int C(int b,int t){return 1ll*fac[b]*inv[t]%mod*inv[b-t]%mod;}
     8 int main(){mu[1]=fac[1]=f[1]=1;
     9     for(int i=2;i<S;++i){
    10         if(!np[i])p[++pc]=i,mu[i]=-1;
    11         for(int j=1,x;j<=pc&&(x=p[j]*i)<S;++j)
    12             if(i%p[j])mu[x]=-mu[i],np[x]=1;
    13             else{np[x]=1;break;}
    14     }for(int i=2;i<S<<1;++i)fac[i]=1ll*fac[i-1]*i%mod;
    15     inv[S*2-1]=pow(fac[S*2-1],mod-2);
    16     for(int i=S*2-2;~i;--i)inv[i]=inv[i+1]*(i+1ll)%mod;
    17     for(int i=2;i<S;++i)f[i]=(f[i-1]+f[i-2])%(mod-1);
    18     for(int i=1;i<S;++i)f[i]=pow(2,f[i])-1;
    19     for(int i=1;i<S;++i)for(int j=i;j<S;j+=i)g[j]=(0ll+g[j]+mu[j/i]*f[i]+mod)%mod;
    20     cin>>t;while(t--){cin>>n>>k;int ans=0;
    21         for(int i=1;i*i<=n;++i)if(n%i==0){
    22             ans=(ans+1ll*C(n/i+k-1,k-1)*g[i])%mod;
    23             if(i*i^n)ans=(ans+1ll*C(i+k-1,k-1)*g[n/i])%mod;
    24         }cout<<1ll*ans*pow(C(n+k-1,n),mod-2)%mod<<endl;
    25     }
    26 }
    View Code

    TrickGCD:

    $Description:$

    You are given an array A , and Zhu wants to know there are how many different array B satisfy the following conditions?
    * $1 le B_i le A_i$
    * For each pair( l , r ) ($1 le l le r le n$) ,$ gcd(b_l,b_{l+1}...b_r) geq 2$

    $n,A_i le 10^5,mod=10^9+7$

    没写正解,懒得写式子了。枚举$gcd$然后容斥。(本质是反演)

    我用$lower bound$水过去了,事实上应该开桶前缀和数论分块来着。。。

    题目名不是说这题可以trick嘛。。。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define mod 1000000007
     4 #define S 100005
     5 int pow(int b,int t,int a=1){for(;t;t>>=1,b=1ll*b*b%mod)if(t&1)a=1ll*a*b%mod;return a;}
     6 int n,t,a[S],mu[S],p[S],pc,ans;char np[S];
     7 int main(){
     8     mu[1]=1;
     9     for(int i=2;i<S;++i){
    10         if(!np[i])p[++pc]=i,mu[i]=-1;
    11         for(int j=1,x;j<=pc&&(x=p[j]*i)<S;++j)
    12             if(i%p[j])np[x]=1,mu[x]=-mu[i];
    13             else {np[x]=1;break;}
    14     }
    15     cin>>t;for(int x=1;x<=t;++x){
    16         cin>>n;for(int i=1;i<=n;++i)scanf("%d",&a[i]);sort(a+1,a+1+n);a[n+1]=mod;
    17         for(int i=2;i<=a[1];++i)if(mu[i]){int bs=1;
    18             for(int j=1,l;j<=n;j=l)l=lower_bound(a+1,a+2+n,(a[j]/i+1)*i)-a,bs=1ll*bs*pow(a[j]/i,l-j)%mod;//,cout<<i<<' '<<j<<' '<<l<<endl;
    19             ans=(0ll+ans-bs*mu[i]+mod)%mod;
    20         }
    21         cout<<"Case #"<<x<<": "<<ans<<endl;ans=0;
    22     }
    23 }
    View Code

    Neko and Function:

    $Description:$

    Neko learnt a new function f(n,k) today.
    f(n,k) is the number of way to select k numbers ai,(ai>1) and $n=prod_{i=1}^{k} a_i $
    Neko thinks this function is too easy, so she want to know $sumlimits_{i=1}^{n} f(i,k)$
    Calculate the sum after mod $10^9+7$
    Note that if n=6, 6=2×3 and n=3×2 are different way.

    首先按照套路出牌的话,我们想方设法研究题目给出的这个函数。

    首先修改它的定义,因为非1这个限制实在麻烦,我们先考虑可以包含1然后再容斥掉就可以。

    $f(n,k)=sumlimits_{d|n} f(frac{n}{d},k-1)$

    然后中间那个整除挺有意思,它相当于把右边卷上了一个$I$

    于是我们有$f_k = I * f_{k-1}$

    但是到这里还是定义式。对于$I$我们肯定是要作出一些英勇的尝试的,我们给它卷一个$mu$

    这样的话$I * mu = epsilon$,式子变成了$f_k * mu =f_{k-1} * epsilon$

    这个东西好像就可以杜教筛了。然而我没有这么写。

    设$F_k(n) = sumlimits_{i=1}^{n} f(i,k)$这里的$f$与题目中含义相同,即不能有1。

    $F_k(n) = sumlimits_{i=1}^{n} sumlimits_{d|i and d eq 1} f(frac{i}{d} ,k-1)$

    $F_k(n) = sumlimits_{d=2}^{n} sumlimits_{i=1}^{frac{n}{d}} f(i,k-1)$

    $F_k(n) = sumlimits_{d=2}^{n} F_{k-1}(frac{n}{d})$

     这样就可以递归求解了,随便记忆化再加个剪枝,复杂度没法算,反正结果比杜教筛稍快就是了。

    虽说正解是$min25$显然不会。所以在$hdu$多测还是跑不出来

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define mod 1000000007
     4 unordered_map<int,int>M[31];
     5 int sch(int k,int n){
     6     if(k==1)return n-1;if(n<1<<k)return 0;
     7     if(M[k].find(n)!=M[k].end())return M[k][n];
     8     int ans=0;for(int i=2,l,N;N=n/i,i<=n;i=l+1)l=n/N,ans=(ans+sch(k-1,N)*(l-i+1ll))%mod;
     9     return M[k][n]=ans;
    10 }
    11 int main(){int n,k;cin>>n>>k;cout<<sch(k,n);}
    至少码长可能还不到杜教筛的四分之一

    GCD of Sequence:

    $Description:$

    Alice is playing a game with Bob.
    Alice shows $N$ integers $a_1, a_2, …, a_N$, and $M$,$ K$. She says each integers $1 le  a_i le  M$.
    And now Alice wants to ask for each $d = 1$ to $M$, how many different sequences $b_1, b_2, …, b_N$. which satisfies :
    1. For each $i = 1…N$, $1 le b[i] le M$
    2. $gcd(b_1, b_2, …, b_N) = d$
    3. There will be exactly $K$ position $i$ that $a_i eq b_i$ ($1 le i le n$)
    Alice thinks that the answer will be too large. In order not to annoy Bob, she only wants to know the answer modulo $1000000007$.Bob can not solve the problem. Now he asks you for HELP!

    $1 le N,M le 3 imes 10^5$

    $sumlimits_{i=1}^{N} sumlimits_{b_i=1}^{M} [gcd(b_i)=d] [sumlimits_{i=1}^{n} [a_i=b_i]=n-k]$

    $sumlimits_{i=1}^{N} sumlimits_{b_i=1}^{frac{M}{d}} [gcd(b_i)] [sumlimits_{i=1}^{n} [a_i=b_id]=n-k]$

    $sumlimits_{p} mu(p) sumlimits_{b_i=1}^{frac{M}{pd}} [sumlimits_{i=1}^{n} [a_i=b_ipd] =n-k]$

    $pd$是$n$的约数。式子到这里就可以做了。考虑选了几个$a$中的数含有相应因子,组合数算出来就行。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define mod 1000000007
     4 #define S 300005
     5 int n,m,k,c[S],t[S],a[S],p[S],mu[S],pc,fac[S],inv[S];char np[S];
     6 int pow(int b,int t,int a=1){for(;t;t>>=1,b=1ll*b*b%mod)if(t&1)a=1ll*a*b%mod;return a;}
     7 int C(int b,int t){return 1ll*fac[b]*inv[t]%mod*inv[b-t]%mod;}
     8 int main(){mu[1]=fac[0]=inv[0]=1;
     9     for(int i=2;i<S;++i){
    10         if(!np[i])p[++pc]=i,mu[i]=-1;
    11         for(int j=1,x;j<=pc&&(x=p[j]*i)<S;++j)
    12             if(i%p[j])mu[x]=-mu[i],np[x]=1;
    13             else{np[x]=1;break;}
    14     }for(int i=1;i<S;++i)fac[i]=1ll*fac[i-1]*i%mod;
    15     inv[S-1]=pow(fac[S-1],mod-2);
    16     for(int i=S-2;i;--i)inv[i]=inv[i+1]*(i+1ll)%mod;
    17     while(scanf("%d%d%d",&n,&m,&k)!=EOF){
    18         for(int i=1;i<=m;++i)a[i]=c[i]=t[i]=0;
    19         for(int i=1,x;i<=n;++i)scanf("%d",&x),c[x]++;
    20         for(int i=1;i<=m;++i)for(int j=i;j<=m;j+=i)t[i]+=c[j];
    21         for(int d=1;d<=m;++d)for(int p=1;p*d<=m;++p)if(t[d*p]>=n-k)
    22             a[d]=(a[d]+1ll*mu[p]*C(t[d*p],n-k)*pow(m/d/p-1,t[d*p]-n+k)%mod*pow(m/d/p,n-t[d*p])%mod+mod)%mod;
    23         for(int i=1;i<=m;++i)cout<<a[i]<<' ';cout<<endl;
    24     }
    25 }
    View Code

    Battlestation Operational:

    $Description:$

    > The Death Star, known officially as the DS-1 Orbital Battle Station, also known as the Death Star I, the First Death Star, Project Stardust internally, and simply the Ultimate Weapon in early development stages, was a moon-sized, deep-space mobile battle station constructed by the Galactic Empire. Designed to fire a single planet-destroying superlaser powered by massive kyber crystals, it was the pet project of the Emperor, Darth Vader, and its eventual commander Grand Moff Wilhuff Tarkin to expound the military philosophy of the aptly named Tarkin Doctrine.
    >
    > — Wookieepedia
    In the story of the Rogue One, the rebels risked their lives stolen the construction plan of the Death Star before it can cause catastrophic damage to the rebel base. According to the documents, the main weapon of the Death Star, the Superlaser, emits asymmetric energy in the battlefield that cause photons to annihilate and burns everything in a single shot.
    You are assigned the task to estimate the damage of one shot of the Superlaser.
    Assuming that the battlefield is an n×n grid. The energy field ignited by the Superlaser is asymmetric over the grid. For the cell at i-th row and j-th column, ⌈i/j⌉ units of damage will be caused. Furthermore, due to the quantum effects, the energies in a cell cancel out if gcd(i,j)≠1 or i<j.
    The figure below illustrates the damage caused to each cell for n=100. A cell in black indicates that this cell will not be damaged due to the quantum effects. Otherwise, different colors denote different units of damages.
    Your should calculate the total damage to the battlefield. Formally, you should compute
    $f(n)=sumlimits_{i=1}^{n} sumlimits_{j=1}^{n} [gcd(i,j)] lceil frac{i}{j} ceil$
    where [(i,j)=1] evaluates to be 1 if gcd(i,j)=1, otherwise 0.

    $T le 10^4,n le 10^6$

    最基本的反演形式。原式得$sumlimits_{p}mu(p) sumlimits_{i=1}^{frac{n}{p}} sumlimits_{j=1}^{frac{n}{p}} lceil frac{i}{j} ceil$

    后面那个二重和式只与$frac{n}{p}$相关。预处理。具体的方法就是差分,在适当的位置$+1$。最后前缀和回来。

    实际用的时候还要数论分块,再前缀和。总的复杂度是$O(n ln n)$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define mod 1000000007
     4 #define S 1000005
     5 int p[S],mu[S],f[S],pc,n,ans;char np[S];
     6 int main(){mu[1]=1;
     7     for(int i=2;i<S;++i){
     8         if(!np[i])p[++pc]=i,mu[i]=-1;
     9         for(int j=1,x;j<=pc&&(x=p[j]*i)<S;++j)
    10             if(i%p[j])mu[x]=-mu[i],np[x]=1;
    11             else{np[x]=1;break;}
    12     }for(int i=2;i<S;++i)mu[i]+=mu[i-1];
    13     for(int i=1;i<S;++i)for(int j=i+1;j<S;j+=i)f[j]++;
    14     for(int i=1;i<S;++i)f[i]++;
    15     for(int i=1;i<S;++i)f[i]=(f[i]+f[i-1])%mod;
    16     for(int i=2;i<S;++i)f[i]=(f[i-1]+f[i])%mod;
    17     while(scanf("%d",&n)!=EOF){
    18         for(int i=1,l,N;N=n/i,i<=n;i=l+1)l=n/N,ans=(ans+(mu[l]-mu[i-1]+mod+0ll)*f[N])%mod;
    19         cout<<ans<<endl;ans=0;
    20     }
    21 }
    View Code
  • 相关阅读:
    机器学习初篇(0.0)
    MQTT 入门介绍
    《八极拳谱》(李书文)
    Golang实战群:日志的处理机制
    【转】火山引擎 Redis 云原生实践
    【转】7000字前端性能优化总结 | 干货建议收藏
    微信小程序canvas绘制圆角边框
    【转】语义化版本 2.0.0
    Verdaccio私有 npm 服务器搭建及其配置
    【转】根据条件配置多个npm仓库
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/12122613.html
Copyright © 2011-2022 走看看