HDU 6053 TrickGCD 【容斥定理】【莫比乌斯函数】
来源:互联网 发布:韩子高网络剧有下部吗 编辑:程序博客网 时间:2024/05/16 06:14
Problem Description
You are given an array A , and Zhu wants to know there are how many different array B satisfy the following conditions?
- 1≤Bi≤Ai
- For each pair( l , r ) (1≤l≤r≤n) , gcd(bl,bl+1…br)≥2
Input
The first line is an integer T(1≤T≤10) describe the number of test cases.
Each test case begins with an integer number n describe the size of array A.
Then a line contains n numbers describe each element of A
You can assume that 1≤n,Ai≤105
Output
For the kth test case , first output “Case #k: ” , then output an integer as answer in a single line . because the answer may be large , so you are only need to output answer mod 109+7
Sample Input
1
4
4 4 4 4
Sample Output
Case #1: 17
题意:
给定数列a,求b数列的不同组成种数,对于b数列的任意子集的gcd≥2。
想法:
从2遍历到
举个栗子,4 5 6 8
x=2时,4和5中都能拿出2,4;6中能拿出2,4,6;8中能拿出2,4,6,8,所以sum1=2*2*3*4=48;
x=3时,4和5中都能拿出3;6和8中都能拿出3,6,所以sum2=2*2=4;
x=4时,4,5,6中都能拿出4;8中能拿出4,8,所以sum3=1*2=2;
x>=4时, 4中已经拿不出数了。
所以sum=sum1+sum2+sum3=54
但会有重复的情况。
比如x=2时,可以取出4 4 4 4,x=4时,也可以取出4 4 4 4。
由此我们发现,我们得出公式sum=
为了处理重复的情况,我们采用专门用来处理重复情况的容斥定理。
我们知道任何≥2的数都可以分解成质因数相乘的情况。
而每一个倍数都只能统计存在一次。
假设我们讨论n, n=p*a,p是最小素因子
①代表此倍数在之前p的次数中已经出现过了,比如n=4=2*2;
②代表每个素数都只会本身出现一次,之前未出现过,比如n=6=2*3;
③比如n=12=2*6,再将6分解成2*3带回最初讨论。
即根据容斥思想,考虑一个数n,假设他能分解成三个质因数相乘:a*b*c,那么在算gcd为a、b、c时分别算了一遍,所以我们要减去gcd为a*b、a*c、b*c的,再加上gcd为a*b*c的。
推广:我们需要加上质因数为奇数个的,减去质因数为偶数个的。当某个质因数的指数大于等于2,那么这个数我们之前肯定算过,所以这个不计入最后答案。
而取反后的莫比乌斯函数正好符合我们的需要,
所以最终公式为sum=
然鹅数很大,这样直接做会超时,所以下面我们来想一想优化的方式。
之前我们是在求出每个数能取到此时的gcd倍数有几个,现在我们把
优化后的式子为:sum=
比如前面栗子中的4 5 6 8
x=2时,取出一个2的范围内(2,3),不存在;取出两个2的范围内(4,5),有4 5 存在;取出三个2的范围内(6,7),6存在;取出四个2的范围(8,9)内,有8存在。所以sum1=
接着再累加求和去重~和优化前一个思路辣~
#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>using namespace std;const int maxn=2e6+10;const int mod=1e9+7;typedef long long ll;bool vis[maxn];ll prime[maxn],mu[maxn],num[maxn],a[maxn];void mobius()//mu[i]表示莫比乌斯函数{ memset(vis,false,sizeof vis); mu[1]=1; int tot=0; for(ll i=2;i<maxn;++i) { if(!vis[i]) { prime[tot++]=i; mu[i]=-1; } for(int j=0;j<tot;++j) { if(i*prime[j]>maxn) break; vis[i*prime[j]]=true; if(i%prime[j]==0) { mu[i*prime[j]]=0; break; } else { mu[i*prime[j]]=-mu[i]; } } }}ll qmod(ll a,ll b){ ll ans=1; while(b) { if(b%2==1) ans=ans*a%mod; a=(a*a)%mod; b/=2; } ans=ans%mod; return ans;}int main(){ mobius(); int t,n; scanf("%d",&t); for(int cnt=1;cnt<=t;++cnt) { scanf("%d",&n); ll minn=maxn; memset(num,0,sizeof num); for(int i=1;i<=n;++i) { scanf("%lld",&a[i]); num[a[i]]++; minn=min(a[i],minn); } for(int i=1;i<maxn;++i) {//num[i]表示≤i的在a数列中的个数 num[i]+=num[i-1]; } ll ans=0; for(ll i=2;i<=minn;++i) { ll sum=1; for(ll j=1;j*i<=100000;++j) {//j表示倍数 sum=(sum*qmod(j,num[(j+1)*i-1]-num[j*i-1])%mod)%mod; } ans=(ans-sum*mu[i]%mod+mod)%mod; } printf("Case #%d: %lld\n",cnt,ans); } return 0;}
ps:沃德天 这个题 说多了都是泪/(ㄒoㄒ)/~~
- HDU 6053 TrickGCD 【容斥定理】【莫比乌斯函数】
- hdu 6053 TrickGCD 容斥 莫比乌斯
- hdu 6053 TrickGCD 【容斥&筛法|莫比乌斯】
- hdu 6053 TrickGCD(容斥,分段,莫比乌斯函数)
- 【 hdu 6053】 TrickGCD 【数论 容斥 + 莫比乌斯函数 】
- hdu6053 TrickGCD 莫比乌斯函数 容斥原理
- TrickGCD(莫比乌斯函数,容斥)
- hdu 6053 TrickGCD 容斥原理(莫比乌斯工具)
- 2017 Multi-University Training Contest 2 && HDOJ 6053 TrickGCD 【容斥+莫比乌斯函数】
- hdu 6053 TrickGCD [莫比乌斯函数]
- Hdu-6053 TrickGCD(莫比乌斯函数)
- HDU 6053 TrickGCD (莫比乌斯函数)
- HDU 6053 TrickGCD(莫比乌斯函数)
- HDU6053-TrickGCD 容斥原理+莫比乌斯反演
- 2017多校训练赛第二场 HDU 6053 TrickGCD(容斥原理/莫比乌斯反演)
- 2017多校联合第二场 1009题 hdu 6053 TrickGCD (超详细!!!)莫比乌斯 容斥
- HDU6053(莫比乌斯函数+容斥定理)
- HDU 6053 TrickGCD(莫比乌斯反演+分块)
- hdu 多校联赛 TrickGCD
- spring+springmvc+hibernate,实现分页功能
- hdu5692(dfs序+线段树 )Snacks
- 设计模式之禅笔记-命令模式
- 异常
- HDU 6053 TrickGCD 【容斥定理】【莫比乌斯函数】
- NOT IN和NOT EXISTS还有不一样的时候哦
- 选择开机自启动服务步骤---Linux系统
- 蝶恋花·伫倚危楼风细细
- hdu 1009 FatMouse' Trade 贪心入门
- 从今天开始,记录开发经历
- ACM集训日记——7月31
- 排序算法之直接插入、希尔排序、堆排序三者比较
- treap平衡树