HDU 5073 Coprime(容斥原理+组合数学)

题意:给出n个数,求出这些数中有多少个三元组(a,b,c),使得(a,b)= 1,(a,c) = 1,(b,c) = 1或
(a,b) != 1,(a,c) != 1,(b,c) != 1。

思路:这道题直接求答案并不好求,可以转化为先求不符合条件的三元组然后用总数减去这个不合法的组合数。

把每一个数考虑成一个点,如果两个数之间互素那么连一条红边,如果不互素连一条黑边,那么问题转化成了经典的双色三角形问题,对于一个点,假设它向外连接了a条红边,那么由这个点可以形成的双色三角形数目为a*(n-1-a),注意到每个三角形被计算了两次最后要除以2.

现在问题变成了求一个序列中与一个数互素的个数,这个可以用容斥来做。

用sumv[i]记录序列a中i的倍数有多少个,因为每个数小于100000,所以每个数有最多不超过6个不同的质因子,可以先预处理出所有数的不同的质因子,然后O(n)把序列扫一遍并对每个元素用状态压缩的方法求出它的所有约数再更新sumv,

对n分解质因子,假设n=p1*p2*...*pw,那么利用容斥,答案就是

m-sigma(sumv[pi])+sigma(sumv[pi*pj])-sigma(sumv[pi*pj*pk])+...(i , j, k不相等)。

//#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <functional>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <bitset>

using namespace std;

#define IOS std::ios::sync_with_stdio(false);std::cin.tie(0)
#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define pr( x ) cout << #x << " = " << x << endl
#define pri( x ) cout << #x << " = " << x << " "
#define test( t ) int t ; cin >> t ; int kase = 1 ; while( t-- )
#define out( kase ) printf( "Case %d: " , kase++ )
#define mp make_pair
#define pii pair<int,int>
#define pli pair<long long,int>
#define pll pair<long long,long long>
#define fs first
#define se second
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;
typedef unsigned long long ULL;
const double eps = 1e-8 ;
const int inf = 0x3f3f3f3f ;
const long long INF = 0x3f3f3f3f3f3f3f3fLL ;

//const int N = ;
const int MAXN = 122200;
int n, a[MAXN];
int vis[MAXN], sumv[MAXN];
int ans[MAXN];
vector<int> prime[MAXN];
void sieve() {
	for(int i = 2; i <= 100000; i++) {
		if(vis[i]) continue;
		prime[i].push_back(i);
		for(int j = i*2; j <= 100000; j += i) {
			vis[j] = 1, prime[j].push_back(i);
		}
	}
}
int main()
{
    //freopen("my.in","r",stdin);
    sieve();
    int T; cin >> T;
    while(T--) {
		cin >> n;
		memset(sumv, 0, sizeof(sumv));
		memset(ans, 0, sizeof(ans));
		for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
		for(int i = 1; i <= n; i++) {
			int tmp = a[i];
			int sz = prime[tmp].size();
			int maxs = (1<<sz) - 1;
			for(int j = 1; j <= maxs; j++) {
				int shit = 1;
				for(int k = 0; k < sz; k++) if((1<<k)&j) {
					shit *= prime[tmp][k];
				}
				sumv[shit]++;
			}
		}
		//puts("Fuck");
		LL ret = (LL)n * (n-1) * (n-2) / 6;
		for(int i = 1; i <= n; i++) {
			int tmp = a[i];
			int sz = prime[tmp].size();
			int maxs = (1<<sz) - 1;
			for(int j = 1; j <= maxs; j++) {
				int shit = 1, cnt = 1;
				for(int k = 0; k < sz; k++) if((1<<k)&j) {
					shit *= prime[tmp][k];
					cnt *= -1;
				}
				ans[i] += cnt * sumv[shit];
			}
			ans[i] += n;
			if(a[i] == 1) ans[i]--;
		}
		//for(int i = 1; i <= 10; i++) cout << i << " " << sumv[i] << endl;
		//for(int i = 1; i <= n; i++) cout << ans[i] << endl;
		LL tmp = 0;
		for(int i = 1; i <= n; i++) {
			tmp += (LL)(ans[i])*(n-1-ans[i]);
		}
		tmp /= 2;
		cout << ret-tmp << endl;
    }
    // freopen("my.out","w",stdout);
    return 0;
}












1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看rEADME.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看rEADME.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值