题目:
题意:
一共有
n
n
n个数,已知有
k
k
k对数的和为正数
问最多有多少对数的乘积为正数
分析:
因为要使得积为正数的对数尽可能的多,所以我们原本的数应该都是些非零的数
这样我们设有
x
x
x个正数,就会有
n
−
x
n-x
n−x个负数
此时积为正数的对数为
x
∗
(
x
−
1
)
2
+
(
n
−
x
)
∗
(
n
−
x
−
1
)
2
\frac{x*(x-1)}{2}+\frac{(n-x)*(n-x-1)}{2}
2x∗(x−1)+2(n−x)∗(n−x−1)
所以显然我们要使得两项中的任意一个尽可能的大,所以我们可以二分
x
x
x的最大值和最小值,在两者中取最大值作为答案
代码:
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define LL long long
using namespace std;
inline LL read()
{
LL s=0,f=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') {s=s*10+c-'0';c=getchar();}
return s*f;
}
LL n=read(),k=read();
LL get(LL x)
{
LL y=n-x;
return (x?x*(x-1)/2:0)+(y?y*(y-1)/2:0);
}
int main()
{
if(k>n*(n-1)/2) return !printf("-1");
LL l=0,r=n,a1=-1;
while(l<=r)
{
LL mid=(l+r)>>1;
if(mid*(mid-1)/2<=k) l=mid+1,a1=mid;
else r=mid-1;
}
l=0;r=n;LL a2=-1;
while(l<=r)
{
LL mid=(l+r)>>1;
if(mid*(n-mid-1)/2>=k) r=mid-1,a2=mid;
else l=mid+1;
}
cout<<max(a1==-1?-1:get(a1),a2==-1?-1:get(a2));
return 0;
}

被折叠的 条评论
为什么被折叠?



