巧解容斥
来源:互联网 发布:淘宝会员信誉怎么提升 编辑:程序博客网 时间:2024/05/21 22:58
hdu 6053
题意:给定一个a序列,让求有多少种b序列满足,b序列的对应值小于等于a序列的值,且b序列的任意区间的数的gcd>=2;
思路:任意区间的数的gcd>=2则说明,b序列任意两个数不互素,这就可以枚举约数,假如约数为k,则a序列的每个数ai的贡献为ai/k向下取整个值,全部乘起来就是约数为k的b序列种类,每种约数之和就是ans,但是会有重复的,后面容斥一下就好了。
#include<cstdio>#include<cmath>#include<cstring>#include<iostream>#include<algorithm>#define LL long longusing namespace std;const int maxn=1e6+10;const LL mod=1e9+7;LL x[maxn],dis[maxn],dp[maxn];LL quickpow(LL a,LL k){ if(a==1||k==0) return 1; LL res=1; while(k) { if(k&1) res=(res*a)%mod; a=(a*a)%mod; k>>=1; } return res;}LL ans[maxn];int main(){ int ncase,Z=0; scanf("%d",&ncase); while(ncase--) { memset(dis,0,sizeof(dis)); memset(dp,0,sizeof(dp)); memset(ans,0,sizeof(ans)); LL n,Min=100010; scanf("%lld",&n); for(int i=0; i<n; i++) { scanf("%lld",&x[i]); Min=min(Min,x[i]); dis[x[i]]++;//数列值域化 /* 后面要求小于等于某个数,是k的倍数的有过少个,如果每次都跑一边n 的话,时间复杂度会很高,但是我们发现1~k-1除k向下取整都是1而 k~2*k-1除k向下取整都是2,所以他们可以看成同一个值,用快速幂求解 */ } for(int i=1; i<=200000; i++)//统计前缀和 dis[i]+=dis[i-1]; for(int k=2; k<=Min; k++)//枚举约数 { LL sum=1; for(int j=k; j<=100000; j+=k)//看约数为k的方案有多少种 { sum=(sum*(LL)quickpow((LL)j/k,dis[j+k-1]-dis[j-1]))%mod; } ans[k]=sum; } for(int i=100000;i>=2;i--)//手动容斥 { dp[i]=ans[i]; for(int j=i+i;j<=100000;j+=i) dp[i]=((dp[i]-dp[j])%mod+mod)%mod; } /* dp[i]代表gcd为i的有多少种,不包括重复的,这就是从后往前容斥的好处,不需要 加两个倍数个倍数,因为他们是不会重复的,比如2和3有6这个公倍数,如果减去了 2和3倍数的数量则6的倍数的数量就减去了2次要加上6的倍数的数量,而从后往前找 到2时,找到6,6代表的只是自己的值,并不会包含自己倍数的值,这样就不用加了 */ LL sum=0; for(int i=2;i<=100000;i++)//统计结果 sum+=dp[i],sum%=mod; printf("Case #%d: %lld\n",++Z,sum); }}
阅读全文
0 0
- 巧解容斥
- net.sqlcipher.database.SQLiteConstraintException: error code 19: UNIQUE constraint failed: xxx
- matlab 正弦波
- js 实现一个简单的3D轮播效果
- 贝尔的面试题:你认为效率最高的方法,实现从1加到100
- Tomcat项目部署方式
- 巧解容斥
- hibernate 5.2.10 的使用
- 【期望】acm题目
- Tomcat部署Web项目
- SSH免密登录
- 开始TensorFlow学习
- HDU 2017 多校联赛2 1003 Maximum Sequence
- iOS中tableView组头部和尾部标题设置
- WPF 毛玻璃效果(转载)