容斥原理po3904j.docxVIP

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
容斥原理po3904j

题意:给出一个数列,让求出数量为4的子集,并且这四个数的最大公约数为1 的个数。数列的个数为10000,并且元素的最大值为10000思路:如果暴利枚举的话,肯定要超时。最开始的时候我发现了用容斥原理可以做,但是我进行容斥原理的时候是用的搜索,就超时了。后来才发现有一个很神奇的方法。这道题我首先学会了求数的因子的一个简单的方法,不用开始打出素数表。其实只需要从2 往后枚举到i*i==n的时候。当枚举到一个数时可以整除的话,那么我就把这个数当成因子,然后把这个数多次除以i,直至没有i因子为止。直至结束。最后如果剩余的数不为1,那么这个数也是一个数因子。Ans = C(n,4)-sum(C(a1j,4))+sum(C(a2j,4))…….aij表示 该数是由4个数因子组成,并且是这种情况的第j个的数目。但是如何求呢,开始我用的是搜索,果断不行,因为10000以内的素数有1000多个,搜索的话果断超时,最后在网上看到一个做法,很神奇,利用到了位运算具体是这样的,我们找出一个数的因子,(不超过6个),然后用位运算来枚举当前的数因子可以组成的数。具体是这样子的for(int i = 1; i (1cnt) ;i++) { sum = 0; now = 1; for(int j = 0 ; j cnt;j++) { if(i(1j)) { sum ++; now *= p[j]; } } count[now]++; num[now] = sum; }最后直接用容斥原理解决就行了 AC代码:#includeiostream#includecstdio#includecstringusing namespace std;const int N = 10100;int count[N],num[N],n;__int64 C[N];void get_C() { for(__int64 i = 4; iN;i++) C[i] = i*(i-1)*(i-2)*(i-3)/24; } void get_count(int n) { int p[N],sum,cnt = 0,x = n,now; for(int i = 2; i*i=n;i++) { if( n%i == 0) { p[cnt++] = i; while(n%i == 0) n /= i; } } if(n != 1) p[cnt++] = n; for(int i = 1; i (1cnt) ;i++) { sum = 0; now = 1; for(int j = 0 ; j cnt;j++) { if(i(1j)) { sum ++; now *= p[j]; } } count[now]++; num[now] = sum; } } void init() { int a; memset(count,0,sizeof(count)); memset(num,0,sizeof(num)); for(int i = 0;i n; i++) { scanf(%d,a); get_count(a); } }int main() { __int64 ans; get_C(); while(scanf(%d,n)!=EOF) { init(); ans = C[n]; for(int i = 2;i = N ;i++) { if(num[i]%2) ans -= C[count[i]]; else ans += C[count[i]]; } printf(%I64d\n,ans); } return 0; }

文档评论(0)

baoyue + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档