日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

转一道容斥原理的题

發(fā)布時間:2025/3/21 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 转一道容斥原理的题 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

源出處:https://blog.csdn.net/qingshui23/article/details/51077728

POJ 3904 Sky Code (容斥原理)

2016年04月06日 19:53:49

閱讀數(shù):827

傳送門

Sky Code

Time Limit:?1000MS?Memory Limit:?65536K
Total Submissions:?2027?Accepted:?650

Description

Stancu likes space travels but he is a poor software developer and will never be able to buy his own spacecraft. That is why he is preparing to steal the spacecraft of Petru. There is only one problem – Petru has locked the spacecraft with a sophisticated cryptosystem based on the ID numbers of the stars from the Milky Way Galaxy. For breaking the system Stancu has to check each subset of four stars such that the only common divisor of their numbers is 1. Nasty, isn’t it? Fortunately, Stancu has succeeded to limit the number of the interesting stars to N but, any way, the possible subsets of four stars can be too many. Help him to find their number and to decide if there is a chance to break the system.

Input

In the input file several test cases are given. For each test case on the first line the number N of interesting stars is given (1 ≤ N ≤ 10000). The second line of the test case contains the list of ID numbers of the interesting stars, separated by spaces. Each ID is a positive integer which is no greater than 10000. The input data terminate with the end of file.

Output

For each test case the program should print one line with the number of subsets with the asked property.

Sample Input

4 2 3 4 5 4 2 4 6 8 7 2 3 4 5 7 6 8

Sample Output

1 0 34

Source

Southeastern European Regional Programming Contest 2008

題目大意:

給出n(n<10000)個數(shù),這些數(shù)<=10000,讓你求的就是 GCD(a,b,c,d) == 1的個數(shù),注意必須是 4 個數(shù)

解題思路:

其實這個題一開始做就像暴力,可是自己又暴不明白,因為 他把這個題歸入容斥原理,所以就考慮GCD(a,b,c,d) ?== 1的反面就是 GCD(a,b,c,d) ?!= 1,那么a, b, c, d 必定有同樣的因子,所以 :

第一步:計算n個數(shù)字選四個總共有多少種選法[ C(n,4) ],然后減去公約數(shù)不是1的。

第二步:由一個素因子組合成的四個數(shù)的組合數(shù)?+ 由兩個素因子組合成的四個數(shù)的組合數(shù) -....+..(奇加偶減)

第三步:進行二進制枚舉,在枚舉的時候要用到兩個數(shù)組 ,_cnt[]:記錄當前因子是由多少個素因子組成, sum[]:記錄當前因子的個數(shù)

第四步:我們先考慮將每一個數(shù) 進行素因子分解,在這里完全可以采用暴力也就是 O(sqrt(n))的算法,因為數(shù)據(jù)不是很大,當然也可以直接進行素數(shù)篩,我采用的就是素數(shù)篩。

最后一步:假設(shè)a是2的因子的個數(shù),b是3的因子的個數(shù),c是6的因子的個數(shù),就是C(n,4) - C(a,4) - C(b,4) + C(c,4)

容斥原理,與第一步差不多...

PS:我還用了輸入輸出外掛,果然快呀 ^_^

My Code:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 1e4+5;
typedef long long LL;
int Scan()///輸入外掛
{
? ? int res=0,ch,flag=0;
? ? if((ch=getchar())=='-')
? ? ? ? flag=1;
? ? else if(ch>='0'&&ch<='9')
? ? ? ? res=ch-'0';
? ? while((ch=getchar())>='0'&&ch<='9')
? ? ? ? res=res*10+ch-'0';
? ? return flag?-res:res;
}
void Out(LL a)///輸出外掛
{
? ? if(a>9)
? ? ? ? Out(a/10);
? ? putchar(a%10+'0');
}
?
int p[MAXN];
bool prime[MAXN];
int k;
void isprime()///素數(shù)篩
{
? ? k = 0;
? ? LL i, j;
? ? memset(prime,false,sizeof(prime));
? ? for(i=2; i<MAXN; i++)
? ? {
? ? ? ? if(!prime[i])
? ? ? ? {
? ? ? ? ? ? p[k++] = i;
? ? ? ? ? ? for(j=i*i; j<MAXN; j+=i)
? ? ? ? ? ? ? ? prime[j] = true;
? ? ? ? }
? ? }
}
int fac[MAXN/100],num[100], cnt;
void Dec(int m)///素因子分解
{
? ? cnt = 0;
? ? memset(num, 0, sizeof(num));
? ? for(int i=0; p[i]*p[i]<=m&&i<k; i++)
? ? {
? ? ? ? if(m%p[i]==0)
? ? ? ? {
? ? ? ? ? ? fac[cnt] = p[i];
? ? ? ? ? ? while(m%p[i]==0)
? ? ? ? ? ? {num[cnt]++;
? ? ? ? ? ? ? ? m /= p[i];
? ? ? ? ? ? }
? ? ? ? ? ? cnt++;
? ? ? ? }
? ? }
? ? if(m > 1)
? ? {
? ? ? ? fac[cnt] = m;
? ? ? ? num[cnt++]=1;
? ? }
? ? ///cout<<cnt<<endl;
? ? ///cout<<fac[0]<<" "<<fac[1]<<endl;
}
int sum[MAXN];///記錄當前因子的個數(shù)
int _cnt[MAXN];///記錄當前因子是由多少個素因子組成
void Get(int m)
{
? ? Dec(m);
? ? for(int i=1; i<(1<<cnt); i++)
? ? {
? ? ? ? int s = 0;
? ? ? ? LL ans = 1;
? ? ? ? for(int j=0; j<cnt; j++)
? ? ? ? {
? ? ? ? ? ? if(i & (1<<j))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? s++;
? ? ? ? ? ? ? ? ans *= fac[j];
? ? ? ? ? ? ? ? if(ans > m)
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? sum[ans]++;
? ? ? ? _cnt[ans] = s;
? ? }
}
LL ak[MAXN];///C(n,4)
void RongChi()
{
? ? memset(ak,0,sizeof(ak));
? ? for(LL i=4; i<MAXN; i++)
? ? ? ? ak[i] = i*(i-1)*(i-2)*(i-3)/24;
}
int main()
{
? ? RongChi();
? ? isprime();
? ? ///Dec(1);
? ? int n, x;
? ? while(~scanf("%d",&n))
? ? {
? ? ? ? memset(sum, 0, sizeof(sum));
? ? ? ? int m = n;
? ? ? ? while(m--)
? ? ? ? {
? ? ? ? ? ? x = Scan();
? ? ? ? ? ? Get(x);
? ? ? ? }
? ? ? ? LL ret = 0;
? ? ? ? for(int i=0; i<MAXN; i++)
? ? ? ? {
? ? ? ? ? ? if(sum[i])
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if(_cnt[i] & 1)
? ? ? ? ? ? ? ? ? ? ret += ak[sum[i]];
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? ? ? ret -= ak[sum[i]];
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? LL ans = ak[n] - ret;
? ? ? ? Out(ans);
? ? ? ? puts("");
? ? }
? ? return 0;
}
?

轉(zhuǎn)載于:https://www.cnblogs.com/linruier/p/9513855.html

《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的转一道容斥原理的题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。