日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

转一道容斥原理的题

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

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

POJ 3904 Sky Code (容斥原理)

2016年04月06日 19:53:49

閱讀數: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)個數,這些數<=10000,讓你求的就是 GCD(a,b,c,d) == 1的個數,注意必須是 4 個數

解題思路:

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

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

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

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

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

最后一步:假設a是2的因子的個數,b是3的因子的個數,c是6的因子的個數,就是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()///素數篩
{
? ? 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];///記錄當前因子的個數
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;
}
?

轉載于:https://www.cnblogs.com/linruier/p/9513855.html

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

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。