A - A+B Again?
将一个两位数的个位和十位相加即可
#include<iostream>
using namespace std;
int main(){
int T;cin>>T;
while(T--){
int n;cin>>n;
cout<<n/10+n%10<<endl;
}
}
B - Card Game
最多只有4种情况,分类判断即可。
#include<iostream>
using namespace std;
int main(){
int T;cin>>T;
while(T--){
int a,b,c,d;
cin>>a>>b>>c>>d;
int ans=0;
if(a>c&&b>=d||a>=c&&b>d) ans+=2;
if(a>d&&b>=c||a>=d&&b>c) ans+=2;
cout<<ans<<endl;
}
}
/*
a c b d
a d b c
*/
C - Showering
排序之后首尾相减就能得到空闲的区间。
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main(){
int T;cin>>T;
while(T--){
int n,s,m;
cin>>n>>s>>m;
vector<pair<int,int>>v;
for(int i=1;i<=n;i++){
int st,ed;cin>>st>>ed;
v.push_back({st,ed});
}
sort(v.begin(),v.end());
int last=0;
int f=0;
for(int i=0;i<v.size();i++){
if(v[i].first-last>=s){
f=1;break;
}else{
last=v[i].second;
}
}
if(m-last>=s) f=1;
if(f) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
D - Slavic’s Exam
使用一个pos指针首先指向s2的第0个位置
遍历s1,当s1中遇到?时,可以插入当前正在匹配到pos的位置上的字母,
遇到字母时,如果和当前正在匹配到pos2的位置上的字母一样时,让pos向后移动也就是pos++
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main(){
int T;cin>>T;
while(T--){
string s1,s2;cin>>s1>>s2;
int pos=0;
for(int i=0;i<s1.length();i++){
if(s1[i]=='?'){
if(pos==s2.length()){
s1[i]='a';
}else{
s1[i]=s2[pos++];
}
}else{
if(s1[i]==s2[pos]) pos++;
}
}
if(pos==s2.length()){
cout<<"YES\n"<<s1<<endl;
}else{
cout<<"NO\n";
}
}
}
E - Triple Operations
预处理、前缀和
首先预处理3的次方的一个数组a
接着预处理前缀和数组pre,使用upper_lower函数查找某个数在a数组中的位置。
预处理完成后再输出,时间复杂度为
O
(
1
)
O(1)
O(1)
#include<iostream>
#include<algorithm>
#define int long long
using namespace std;
const int MAXN=2e5+10;
int pre[MAXN],a[20]; ;
signed main(){
pre[1]=1; a[0]=1;
for(int i=1;i<20;i++) a[i]=a[i-1]*3;
for(int i=2;i<MAXN;i++) pre[i]=pre[i-1]+upper_bound(a,a+20,i)-a;
int T;cin>>T;
while(T--){
int l,r;cin>>l>>r;
cout<<pre[l]+pre[r]-pre[l-1]*2<<endl;
}
}
F - Expected Median
这道题注意快速求解组合数,MOD是一个质数,使用费马小定理求解组合数
#include<iostream>
#define int long long
using namespace std;
const int MOD=1e9+7;
const int N=2e6+10;
int fact[N],infact[N];
int qpow(int a,int b){
int res=1;
while(b){
if(b&1) res=res*a%MOD;
a=a*a%MOD; b>>=1;
}
return res;
}
void ini(){
fact[0]=infact[0]=1;
for(int i=1;i<N;i++){
fact[i]=fact[i-1]*i%MOD;
infact[i]=qpow(fact[i],MOD-2);
}
}
int C(int a,int b){
if(a<b) return 0;
return fact[a]*infact[b]%MOD*infact[a-b]%MOD;
}
signed main(){
ini();
int T;cin>>T;
while(T--){
int n,k;cin>>n>>k;
int a[n+2];
int cnt1=0;
for(int i=1;i<=n;i++) {
cin>>a[i];if(a[i]) cnt1++;
}
int ans=0;
for(int i=(k+1)/2;i<=min(k,cnt1);i++){
ans+=(C(cnt1,i)*C(n-cnt1,k-i))%MOD;
ans%=MOD;
}
cout<<ans<<endl;
}
}
G1 - Ruler (easy version)
l o g 3 999 = 6.28 log_3999=6.28 log3999=6.28 ,题目给出7次机会可以满足三分查找。
对于一个区间 [ l , r ] [l,r] [l,r]来说,将他分为3份,得到 [ l , l + ( r − l ) / 3 ] , [ l + ( r − l ) / 3 , r − ( r − l ) / 3 ] , [ r − ( r − l ) / 3 , r ] [l,l+(r-l)/3],[l+(r-l)/3,r-(r-l)/3],[r-(r-l)/3,r] [l,l+(r−l)/3],[l+(r−l)/3,r−(r−l)/3],[r−(r−l)/3,r],令两个中间的点分别为 l m i d 、 r m i d lmid、rmid lmid、rmid。
一个目标
x
x
x在区间
[
l
,
r
]
[l,r]
[l,r]上,
假如
l
m
i
d
、
r
m
i
d
lmid、rmid
lmid、rmid都符合合条件,那么缩小区间
r
=
l
m
i
d
r=lmid
r=lmid,
假如
l
m
i
d
、
r
m
i
d
lmid、rmid
lmid、rmid都不符合条件,那么缩小区间
l
=
r
m
i
d
l=rmid
l=rmid,
假如
l
m
i
d
lmid
lmid符合,
r
m
i
d
rmid
rmid不符合条件,那么缩小区间
l
=
l
m
i
d
+
1
,
r
=
r
m
i
d
−
1
l=lmid+1,r=rmid-1
l=lmid+1,r=rmid−1,
不存在
l
m
i
d
lmid
lmid不符合,
r
m
i
d
rmid
rmid符合条件的情况,因为
l
m
i
d
lmid
lmid始终在
r
m
i
d
rmid
rmid左边。
#include<iostream>
#define int long long
using namespace std;
int check(int l,int r){
cout<<'?'<<' '<<l<<' '<<r<<'\n';
int res;cin>>res;
if(l*r==res) return 1;
if(l*(r+1)==res) return 2;
if((l+1)*(r+1)==res) return 3;
return 0;
}
signed main(){
int T;cin>>T;
while(T--){
int l=2,r=999;
while(l<=r){
int lmid=l+(r-l)/3;
int rmid=r-(r-l)/3;
int res=check(lmid,rmid);
if(res==1) l=rmid+1;
else if(res==2) l=lmid+1,r=rmid-1;
else if(res==3) r=lmid-1;
}
cout<<'!'<<' '<<l<<'\n';
}
}
G2 - Ruler (hard version)
#include<iostream>
#define int long long
using namespace std;
int check(int l,int r){
cout<<'?'<<' '<<l<<' '<<r<<'\n';
int res;cin>>res;
if(l*r==res) return 1;
if(l*(r+1)==res) return 2;
if((l+1)*(r+1)==res) return 3;
return 0;
}
signed main(){
int T;cin>>T;
while(T--){
int l=2,r=999;
while(l<=r){
int lmid=l+(r-l)/3;
int rmid=r-(r-l)/3;
int res=check(lmid,rmid);
if(res==1) l=rmid+1;
else if(res==2) l=lmid+1,r=rmid-1;
else if(res==3) r=lmid-1;
}
cout<<'!'<<' '<<l<<'\n';
}
}