cf962:D.Fun(三元)

题目

给定两个整数 𝑛n 和 𝑥x ,求 𝑎𝑏+𝑎𝑐+𝑏𝑐≤𝑛ab+ac+bc≤n 和 𝑎+𝑏+𝑐≤𝑥a+b+c≤x 的个正整数的三联数( 𝑎,𝑏,𝑐a,b,c )的个数。

注意顺序问题(例如 ( 1,1,21,1,2 ) 和 ( 1,2,11,2,1 ) 被视为不同), 𝑎a , 𝑏b , 𝑐c 必须严格大于 00 。

输入

第一行包含一个整数 𝑡t ( 1≤𝑡≤1041≤t≤104 ) - 测试用例数。

每个测试用例包含两个整数 𝑛n 和 𝑥x ( 1≤𝑛,𝑥≤1061≤n,x≤106 )。( 1≤𝑛,𝑥≤1061≤n,x≤106 ).

保证所有测试用例中 𝑛n 的总和不超过 106106 ,所有测试用例中 𝑥x 的总和不超过 106106 。

输出

输出一个整数 - 𝑎𝑏+𝑎𝑐+𝑏𝑐≤𝑛ab+ac+bc≤n 和 𝑎+𝑏+𝑐≤𝑥a+b+c≤x 的正整数三元组( 𝑎,𝑏,𝑐a,b,c )的个数。

做法

这题就直接枚举a,b,然后求c的最大值中的最小值(n和x分别可以求一个最小值)就好了。

为什么两重循环1e6的范围不会爆呢,因为枚举第二重b的时间复杂度是log(n)的。官方解释是这样的:因为 ab+ac+bc≤n ,我们至少知道 ab≤n 。除以两边得到 b≤na 。当 a=1 时, b 有 n 个选择。当 a=2 时, b 有 n/2 个选择。因此, b 总共有 n+n/2+n/3+...+n/n 个选项。这仅仅是调和数列。因此总复杂度是n*log(n)

#include<bits/stdc++.h> 
using namespace std;
int t;
int n,x;
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n,&x);
		long long ans=0;
		for(int i=1;i<=x-2;i++){//枚举a
			for(int j=1;j<=x-2;j++) {//枚举b
				if(i*j>=n) break;
				if(i+j>=x) break;
				int k=(n-i*j)/(i+j);//算出c
				ans+=min(k,x-i-j);//c的最大值的最小值 
			}
		}
		cout<<ans<<endl; 
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值