南京理工大学校赛 D triple (容斥) 3个数互质的方案数

本文探讨了如何在给定整数n的情况下,计算从1到n中选择三个不同数字使得它们的最大公约数等于m的方案数量。通过简化问题到考虑数字的倍数,利用组合数学的方法来解决此问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                                             triple

                                                                                                  Time Limit:3000MS

                                                                                             Memory Limit:65536KB

Description

给出一个整数n,表示1,2,...,n。从这n个数中任意选择3个不同的数字x,y,z,问x,y,z的最大公约数等于m的方案有多少种?(注意:(1,2,3),(1,3,2),(2,1,3),(2,3,1),(3,1,2),(3,2,1)属于同一种方案)

Input

第一行输入一个整数T(1 <= T <= 100),表示有T组数据,接下来T行,每行2个整数n, m(1 <= m <= n <= 10^5)

Output

输出一个整数表示答案

Sample Input

1
5 1

Sample Output

10


题目和提交链接点击打开链接


思路求gcd(x,y,z)==m的方案数,那么x,y,z肯定是m的倍数,所有只考虑倍数就可以了。倍数的个数d=n/m,其实就可以转化为求1~d中三个不同的数的gcd==1 的情况。那么方案数 = 总情况数(C(d,3) )    -     gcd=(2,3,4......d)的情况数。dp[a]表示gcd==a的情况,1~d中a的倍数有b=(d/a)个,dp[a]=C(b,3) - dp[ 2a,3a,4a...] 。


详细见代码:

//复杂度接近于O(n)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
typedef unsigned long long LLu;
typedef long long LL;
const int maxn=1e5+100;
LL dp[maxn];
int A[maxn];
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n,m;
		int i;
		memset(dp,0,sizeof dp);
		scanf("%d%d",&n,&m);
		n=n/m;
		LL ans=(LL)n*(n-1)*(n-2)/6;
		for(i=n;i>=2;i--)//一开始循环方向写反了浪费了一对堆时间
		{
			int a=n/i;
			dp[i]+=(LL)a*(a-1)*(a-2)/6;
			int b=i;
			b+=i;
			while(b<=n)
			{
				dp[i]-=dp[b];
				b+=i;
			}
		}
		for(i=2;i<=n;i++)
		{
			ans-=dp[i];
		}
		cout<<ans<<endl;
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值