poj3904 Sky Code 容斥原理

来源:互联网 发布:前端常见js兼容性问题 编辑:程序博客网 时间:2024/05/12 23:46

五六个小时才过~本题过的人很少,看起来还是比较难的,但是看到跟组合数目有关系的,就先想到了容斥原理,由于选出的四个数的约数只有1,如此不妨先对每个数进行素因子分解,用每个数的素因子再去重新组合成其它数,再应用容斥定理即可,可是想确实是想好了,可是就是敲不出来,尝试了三个多小时,最终还是没敲出来,没办法 可能刚接触数论 ,对一些特殊处理不是很熟悉,想不到 所以参考了别人的 一下,看到他跟我思路也是大差不差,可是 用了一个二维数组用的很巧妙,比我的 好表达的多


http://blog.csdn.net/jayye1994/article/details/9034277


#include<iostream>#include<cstdio>#include<list>#include<algorithm>#include<cstring>#include<string>#include<queue>#include<stack>#include<map>#include<vector>#include<cmath>#include<memory.h>#include<set>#define ll long long#define LL __int64#define eps 1e-8#define inf 0xfffffffconst ll INF = 1ll<<61;using namespace std;//vector<pair<int,int> > G;//typedef pair<int,int> P;//vector<pair<int,int>> ::iterator iter;////map<ll,int>mp;//map<ll,int>::iterator p;//int dp[100][10000+5];//dp[i][j]表示由i个素因子组成数j的个数;int a[100],b[100];int maxn;void clear(){memset(a,0,sizeof(a));memset(b,0,sizeof(b));memset(dp,0,sizeof(dp));}void dfs(int cnt,int num,int top){if(num==top){int j=1;for(int i=0;i<top;i++)j*=b[i];dp[top][j]++;}elsefor(int i=cnt;i<maxn;i++){b[num]=a[i];dfs(i+1,num+1,top);}}int main(void){ll n;while(cin>>n){clear();for(int i=0;i<n;i++){memset(a,0,sizeof(a));int cnt=0;int x;scanf("%d",&x);for(int j=2;j<=x/2;j++){if(x%j==0){while(x%j==0)x/=j;a[cnt++]=j;}}if(x!=1)a[cnt++]=x;maxn=cnt;for(int j=0;j<cnt;j++)dfs(0,0,j+1);}ll ans=n*(n-1)*(n-2)*(n-3)/24;//选出四个星星的 组合数目,注意去重for(int i=1;i<=22;i++)//大致算算范围内最多可以由多少个素因子组成{for(int j=2;j<=10000;j++){if(dp[i][j]>=4){ll tmp=1;for(int k=dp[i][j];k>dp[i][j]-4;k--)tmp*=k;tmp/=24;if(i&1)//容斥定理,若是由奇数个素因子组成的四个数则减去 他们的组合数目ans-=tmp;elseans+=tmp;//若是有偶数个素因子组成的四个数则加上  他们的组合数目}}}cout<<ans<<endl;}}


原创粉丝点击