A | B | C | D | E | F | G |
AC | AC | TLE(AC) | ------(AC) | ------(AC) | ------ | ------ |
A Two Vessels
题意:你有两个容器,一个装有a克水,一个装有b克水,此时你还有个能装c克水的容器,
求使两个容器中的水质量相等所需的最小移动次数
题解:
可以直接计算出倒水的次数:
代码:
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
int main(){
int n;
cin>>n;
while(n--){
int a,b,c;
cin>>a>>b>>c;
int k=abs(a-b);
int ans=ceil(k/2.0/c);
cout<<ans<<endl;
}
return 0;
}
B The Corridor or There and Back Again
题意:有无限个房间,其中有n个房间,有标号di和陷阱形成的时间si,如果你第t秒到达第i个房间,那么陷阱就会在第t+si秒后激活。
问打印最大的k允许前往房间k然后返回房间1而不会遇到活动陷阱。
题解:
当si为奇数时,最多可以走到 个房间
当si为偶数时,最多可以走到 个房间
求出每一个最多可以到达的房间 ,并不断求出最小值。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
int main(){
int t;
cin>>t;
while(t--){
int n;
cin>>n;
int mn=INT_MAX;
while(n--){
int a,b;
cin>>a>>b;
int s;
s=a+(b-1)/2;
mn=min(mn,s);
}
cout<<mn<<endl;
}
return 0;
}
C Non-coprime Split
题意:有两个整数l和r,找出一对正整数a和b,分别满足以下两种情况:
- l≤a+b≤r
- gcd(a,b)≠1
如果不存在就输出-1
题解:
找到一个i,满足(2<=i<=sqrt(r)),定义一个k=r/i,如果k*i>=l,且k>1,则i和(k-1)*i必然是l和r之间
gcd(i,(k-1)*i)=i!=1的符合要求的整数。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
int main(){
int n;
cin>>n;
while(n--){
int l,r;
cin>>l>>r;
bool flag=false;
for(int i=2;i<=sqrt(r);i++){
int k=r/i;
if(k*i>=l&&k>1){
cout<<i<<" "<<(k-1)*i<<endl;
flag=true;
break;
}
}
if(flag==false) cout<<-1<<endl;
}
return 0;
}
gcd的写法
long long gcd(long long a,long long b){
while(a^=b^=a^=b%=a);
return b;
}
long long gcd(long long a,long long b){
if(a%b==0) return b;
return gcd(b,a%b);
}
D Plus Minus Permutation
题意
你有三个整数,n,x,y在,把排列P的得分称为p1.....pn的值,
求(p1⋅x+p2⋅x+…+p⌊nx⌋⋅x)−(p1⋅y+p2⋅y+…+p⌊ny⌋⋅y)的最大值
思路:
使被减数尽可能的大,减数尽可能的小。把大数放到 x 上,小数放到 y上。
最终答案为
ans=
代码:
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
long long gcd(long long a,long long b){
while(a^=b^=a^=b%=a);
return b;
}
int main(){
long long t;
cin>>t;
while(t--){
long long n,x,y;
cin>>n>>x>>y;
long long ans=0;
long long k=n/(x/gcd(x,y)*y);
ans+=(n+n-(n/x-k)+1)*(n/x-k)/2;
ans-=(1+(n/y-k))*(n/y-k)/2;
cout<<ans<<endl;
}
return 0;
}
E Data Structures Fan
题意:
给定一个长度为 n 的数组和一个长度为 n 的二进制串 s,现有两个操作:
1 l r
,表示将 l≤i≤r 的所有 si 取反(00 变 11,11 变 00);2 g
(∈{0,1})(g∈{0,1}),表示将所有si=g 的 ai 求异或和;
1≤n≤105,1≤t≤104.
思路:
异或的性质:
0^n=n n^0=n n^n=0
用到异或前缀和:s[i]=s[i-1]^a[i];
s0:计算所有si=0的数字ai异或的和
s1: 计算所有si=1的数字ai异或的和
求a[l]到a[r]的异或值:s[r]^s[l-1]
替换:s0^=s[r]^s[l-1]
s1^=s[r]^s[l-1]
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn],s[maxn],ans[maxn];
int main(){
int t;
cin>>t;
while(t--){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
s[i]=s[i-1]^a[i];
}
string c;
cin>>c;
int s1=0,s0=0;
for(int i=0;i<c.size();i++){
if(c[i]=='0'){
s0^=a[i+1];
}
if(c[i]=='1'){
s1^=a[i+1];
}
}
int m,o=0;
cin>>m;
while(m--){
int k;
cin>>k;
if(k==2){
int p;
cin>>p;
if(p==0) ans[++o]=s0;
if(p==1) ans[++o]=s1;
}
if(k==1){
int l,r;
cin>>l>>r;
s0^=(s[r]^s[l-1]);
s1^=(s[r]^s[l-1]);
}
}
for(int i=1;i<=o;i++){
cout<<ans[i]<<" ";
}
cout<<endl;
}
return 0;
}
总结
注重思维能力的提升。