D: worst case
题目大意:给定
a,b
a
,
b
求最大可能的
x∗y<a∗b
x
∗
y
<
a
∗
b
的二元组
(x,y)
(
x
,
y
)
的对数,前提是对于这些二元组,每个
x
x
或每个只可以出现一次
思路:这个题目是真的考思维啊,后面问了xsc大佬才算稍微搞懂了正解的做法,其实也是很结论的。我们先统计
x≤y
x
≤
y
的二元组(x,y)的对数,最后再乘二就可以了,不难发现,如果要求最大的对数的话,那么对于每一个
x
x
都是成立的,又因为,所以x的上限是
d=⌊ab−−√⌋
d
=
⌊
a
b
⌋
,我们既而设
ans=2∗d−1
a
n
s
=
2
∗
d
−
1
,减一是因为要减去
(a,b)
(
a
,
b
)
,但是有几种特殊情况是要考虑的:1.当
d∗(d−1)>=ab
d
∗
(
d
−
1
)
>=
a
b
时,很明显,在
d
d
这个点满足条件的点对不是而是
(d,d)
(
d
,
d
)
所以这里的贡献是不可以算两次的,当出现这种情况的时候,
ans
a
n
s
需要减一。2.当
ab
a
b
本身是完全平方数的时候,由于我们求的是严格小于
ab
a
b
的对数,所以
d
d
在的时候也是不满足情况的,所以又需要减一,这时需要注意
a
a
是否等于,若等于,由于前面已经减过了,所以刚才的减一是没有必要的。
看代码也许更好理解
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
void File(){
freopen("ARC94D.in","r",stdin);
freopen("ARC94D.out","w",stdout);
}
#define REP(i,a,b) for(register int i=a;i<=b;++i)
#define DREP(i,a,b) for(register int i=a;i>=b;--i)
#define MREP(i,x) for(register int i=beg[x];i;i=E[i].last)
#define ll long long
int n;
int main(){
File();
scanf("%d",&n);
REP(i,1,n){
ll a,b;
scanf("%lld%lld",&a,&b);
ll d=sqrt(a*b),ans=d*2-1;
if(d*(d+1)>=a*b)ans--;
if(d*d==a*b && a!=b)ans--;
cout<<ans<<endl;
}
return 0;
}
E: Tozan and Gezan
题目大意:两个人玩游戏,对于A和B两个序列,每个序列的元素和相等,甲每次选A中的一个正数减一,乙每次选B中的一个正数减一,直到两个序列完全相同的时候游戏结束,而甲希望游戏能够进行的更加地长,乙则相反,求在最优的情况下甲可以进行的游戏轮数
思路:由于元素和相等,不难发现,最后的状态就是A序列只剩一个非零元素,而甲不得不去选择它,当乙选择完其他的元素的时候刚好甲不得不选择的元素等于了B序列中对应的那个元素,所以甲希望B中那个元素最小,所以答案即为
sumA−minB
s
u
m
A
−
m
i
n
B
。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
void File(){
freopen("ARC94E.in","r",stdin);
freopen("ARC94E.out","w",stdout);
}
#define REP(i,a,b) for(register int i=a;i<=b;++i)
#define DREP(i,a,b) for(register int i=a;i>=b;--i)
#define MREP(i,x) for(register int i=beg[x];i;i=E[i].last)
#define ll long long
int n;
ll ans,c=0x3f3f3f3f;
bool flag=1;
int main(){
File();
scanf("%d",&n);
REP(i,1,n){
ll a,b;
scanf("%lld%lld",&a,&b);
ans+=a;
if(a>b && b<c)c=b;
if(a!=b)flag=0;
}
if(flag){
cout<<0<<endl;
return 0;
}
cout<<ans-c<<endl;
return 0;
}