简单反演

不知道为啥学长就讲了一波这么高能的东西

甚至没讲gcd,没讲蒙蔽乌斯函数就开始讲反演

不过这个东西是真滴神奇

我就不xjb乱写了,推一篇博客吧

https://www.cnblogs.com/linyujun/p/5210650.html

其实殊途同归,反演出来的式子和容斥出来的是一样的

数学真xx优雅

我xjb写两句,感觉反演反演就是正难则反的意思

比如花盆问题里面用色的问题,恰好用k种难以计算,但是用不超过k种就容易的多,

然后我们利用公式用好求的f推出不好求的g,很优雅

然后蒙蔽乌斯反演

https://www.cnblogs.com/linyujun/p/5210772.html

博主没有写完就逃跑了,不知道干啥去了

(像我这样懒得写的人好像更可恶23333)

然后看一道题 CodeForces - 803F

题意:求一个序列的互质子序列的个数

也就是gcd==1的序列个数

哇好难

我们先考虑gcd为x的

哇还是好难

那我们就先考虑gcd为x的倍数的序列个数 设为gx

我们找出x的倍数有几个(t个),然后随便选,就是2^t种,然后不空 2^t-1种

然后施展反演 fx为gcd==x的序列个数,筛一下莫比乌斯函数,然后套一下板子

最后gcd==1就是1的倍数都施展一遍

#include<cstdio>
#include<cstring>
#include<iostream>
#define maxn 500010
#define ll long long
using namespace std;
int n,x,c[maxn],mu[maxn],prime[maxn],tot,f[maxn];
bool not_prime[maxn];
const ll mod=1000000007;
Mbs(){
    mu[1]=1;
    for(int i=2;i<=100000;i++){
        if(!not_prime[i]){
            prime[++tot]=i;
            mu[i]=-1;
        }
        for(int j=1;prime[j]*i<=100000;j++){
            not_prime[prime[j]*i]=1;
            if(i%prime[j]==0){
                mu[prime[j]*i]=0;break;
            }
            mu[prime[j]*i]=-mu[i];
        }
    }
}
void C(){
    for(int i=1;i<=100000;i++)
        for(int j=i;j<=100000;j+=i)
            c[i]+=f[j];
}
ll Mi(ll x,ll y){
    if(y==0)return 1;
    ll res=Mi(x,y/2);res*=res;res%=mod;
    if(y&1)res*=x;res%=mod;return res;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&x);f[x]++;
    }Mbs();C();ll ans=0;
    for(int i=1;i<=100000;i++){
        ans+=mu[i]*(Mi(2,c[i])-1+mod)%mod;
        ans+=mod;ans%=mod;
    }
    printf("%lld
",ans);
    return 0;
}
View Code

然后看一道不简单的简单题

CodeForces - 776E 

哇这题目一看吓死人啊,然后仔细研究一下f的定义,好像就是欧拉函数啊,然后g(x)就是x

然后变成简单题.......(别忘了取膜)

至于怎么看出来的是欧拉函数,这个,,,,看脸(jilei)吧

推两个比较有用的东西

贾志鹏 线性筛 积性函数  https://wenku.baidu.com/view/2d706761aa00b52acec7ca63.html

原文地址:https://www.cnblogs.com/yanlifneg/p/9511608.html