不知道为啥学长就讲了一波这么高能的东西
甚至没讲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; }
然后看一道不简单的简单题
哇这题目一看吓死人啊,然后仔细研究一下f的定义,好像就是欧拉函数啊,然后g(x)就是x
然后变成简单题.......(别忘了取膜)
至于怎么看出来的是欧拉函数,这个,,,,看脸(jilei)吧
推两个比较有用的东西
贾志鹏 线性筛 积性函数 https://wenku.baidu.com/view/2d706761aa00b52acec7ca63.html