提示:没写第五题,有点小难
一、比赛分数
A,B,C,F题AC,D题对了一个测试点,其余没有考虑
二、比赛过程
先考虑A题,虽然简单,但也难了我几分钟,B题很轻松,到了C题就上难度了,虽然知道是二分但一点也不好写,但至少也写出来了,D题没思路就看了F题,发现特别水就A了,最后D题想到了方法但因为低级错误没有及时A掉,只对了一点(60分之1)。
三、解题报告
1.石头游戏
情况:赛中AC
题意:已知一个长度为 n 的整数序列,每次都只能删掉最左或最右的一个数字,求最少多少次,可以把最小值和最大值都删掉。
题解方法:分三种方法讨论,从两头找,从左边找,从右边找,输出最小值。
题解代码:
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define CLOSE std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define N 1000005
#define M 100005
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define mod 1000000007
using namespace std;
ll a[N],maxx=-inf,minn=inf,cnt1,cnt2,cnt3;
int main(){
CLOSE;
ll t;
cin>>t;
while(t--){
ll n;
cin>>n;
maxx=-inf,minn=inf;
cnt1=0,cnt2=0,cnt3=0;
if(n==1){
cout<<1<<endl;
continue;
}
for(int i=1;i<=n;i++){
cin>>a[i];
maxx=max(maxx,a[i]);
minn=min(minn,a[i]);
}
for(int i=1;i<=n;i++){
cnt1++;
if(a[i]==maxx||a[i]==minn){
break;
}
}
for(int i=n;i>=1;i--){
cnt1++;
if(a[i]==maxx||a[i]==minn){
break;
}
}
ll flag1=0,flag2=0;
for(int i=1;i<=n;i++){
cnt2++;
if(a[i]==maxx){
flag1=1;
}
if(a[i]==minn){
flag2=1;
}
if(flag1==1&&flag2==1){
break;
}
}
flag1=0,flag2=0;
for(int i=n;i>=1;i--){
cnt3++;
if(a[i]==maxx){
flag1=1;
}
if(a[i]==minn){
flag2=1;
}
if(flag1==1&&flag2==1){
break;
}
}
// cout<<cnt1<<" "<<cnt2<<" "<<cnt3<<endl;
cout<<min(cnt1,min(cnt2,cnt3))<<endl;
}
return 0;
}
2.朋友与糖果
情况:赛中AC
题意:已知一个长度为 n 的整数序列,第 i 个整数表示第 i 个朋友的糖果数,从中选 k 个整数,这些整数的总糖果数可以重新分配到 n 个数字中,使得n个数字全部相同。求最小的 k 。
题解方法:选出来重新分配的糖果数肯定有最大的数字,还要知道平均值是多少,这是分配的目标,那么超过这个平均值的,都是我们应该选出来重新分配的。
题解代码:
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define CLOSE std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define N 1000005
#define M 100005
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define mod 1000000007
using namespace std;
ll t,n,a[N];
int main(){
CLOSE;
cin>>t;
while(t--){
cin>>n;
ll sum=0,k=0;
for(int i=1;i<=n;i++){
cin>>a[i];
sum+=a[i];
}
if(sum%n!=0){
cout<<-1<<endl;
continue;
}
sum/=n;
for(int i=1;i<=n;i++){
if(sum<a[i]){
k++;
}
}
cout<<k<<endl;
}
return 0;
}
3.符合要求的对数
情况:赛中AC
题意:给一个数组,求有多少对元素相加结果在 [l,r] 之间。
题解方法:先排序,可以采取二分的方法,在固定一个数后进行二分,找到符合要求的最大数和最小数,如过符合要求,累加下标的差。
题解代码:
#include<bits/stdc++.h>
#define CLOSE ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define isd(c) ('0' <= (c) && (c) <= '9')
#define isa(c) ('a' <= (c) && (c) <= 'z')
#define isA(c) ('A' <= (c) && (c) <= 'Z')
#define mem(a, b) memset(a, b, sizeof a);
#define N 1000005
#define M 2000005
#define inf 0x3f3f3f3f
#define infll 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define PI acos(-1)
#define endl "\n"
#define pii pair<long long,long long>
#define F first
#define S second
#define bug cout << endl << " .....here!...." << endl;
// #pragma GCC optimize("O3")
//#define Time (double)clock() / CLOCKS_PER_SEC <= 0.95
//using namespace __gnu_cxx;
//using namespace __gnu_pbds;
using namespace std;
ll a[N], cnt;
int main() {
CLOSE;
ll t;
cin >> t;
while (t--) {
ll n, l, r;
cin >> n >> l >> r;
cnt = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; i++) {
ll x = a[i];
ll y = lower_bound(a+i+1,a+n+1,l-a[i])-a;
ll z=upper_bound(a+i+1,a+n+1,r-a[i])-a;
z--;
if(y>z){
continue;
}
else{
cnt+=z-y+1;
}
}
cout << cnt << endl;
}
return 0;
}
4.除法问题
情况:赛中A了1个测试点,补题正确。
题意:给我们两个整数 a 和 b,判断能否恰好 k 步除法运算(每次都要整除)使得两数相等。
题解方法:我们可以先求出a和b变成相同的最多除多少步,显然是都变成1,每次除素因子,步数最多,所以统计a 和 b 的素因子个数即可,a最多ak步,b最多bk步,总共最多ak + bk 步。
要想再少的步数,可以多个素因子凑一个合数除法运算,但是想要再多的步数 ( > ak+bk) 就不可以了。比较特殊的是当k==1,不能直接和 ak + bk 比较,因为k是1,只能对其中一个数除法,另一个数不能变,那就表示必须有倍数关系,且不相同。
注意:这里能用 int 就不用 long long 了,防止时间超限!!!!!
题解代码:
#include<bits/stdc++.h>
#define CLOSE ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define isd(c) ('0' <= (c) && (c) <= '9')
#define isa(c) ('a' <= (c) && (c) <= 'z')
#define isA(c) ('A' <= (c) && (c) <= 'Z')
#define mem(a, b) memset(a, b, sizeof a);
#define N 1000005
#define M 2000005
#define inf 0x3f3f3f3f
#define infll 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define PI acos(-1)
#define endl "\n"
#define pii pair<long long,long long>
#define F first
#define S second
#define bug cout << endl << " .....here!...." << endl;
#pragma GCC optimize("O3")
//#define Time (double)clock() / CLOCKS_PER_SEC <= 0.95
//using namespace __gnu_cxx;
//using namespace __gnu_pbds;
using namespace std;
int cnt,w1=0,w2=0,cnt1,cnt2,base1[N],base2[N];
void fen1(int n){
w1=0;
for(int i=2;i*i<=n;i++){
if(n%i==0){
n=n/i;
w1++;
while(n%i==0){
n=n/i;
w1++;
}
}
}
if(n>1){
w1++;
}
}
void fen2(int n){
w2=0;
for(int i=2;i*i<=n;i++){
if(n%i==0){
n=n/i;
w2++;
while(n%i==0){
n=n/i;
w2++;
}
}
}
if(n>1){
w2++;
}
}
int main() {
CLOSE;
int t;
cin>>t;
while (t--) {
int a,b,k;
cin>>a>>b>>k;
if(k==1){
if(a==b){
cout<<"NO"<<endl;
continue;
}
if(max(a,b)%min(a,b)==0){
cout<<"YES"<<endl;
continue;
}
else{
cout<<"NO"<<endl;
continue;
}
}
fen1(a);
fen2(b);
if(w1+w2>=k){
cout<<"YES"<<endl;
continue;
}
else{
cout<<"NO"<<endl;
continue;
}
}
return 0;
}
5.有趣的加法
情况:赛中AC
题意:给我们两个整数 a 和 b,判断能否恰好 k 步除法运算(每次都要整除)使得两数相等。
题解方法:变化1位的次数就是b-a,变化两位就是这两个除以10再作差,以此类推。
题解代码:
#include<bits/stdc++.h>
#define CLOSE ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define isd(c) ('0' <= (c) && (c) <= '9')
#define isa(c) ('a' <= (c) && (c) <= 'z')
#define isA(c) ('A' <= (c) && (c) <= 'Z')
#define mem(a, b) memset(a, b, sizeof a);
#define N 1000005
#define M 2000005
#define inf 0x3f3f3f3f
#define infll 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define PI acos(-1)
#define endl "\n"
#define pii pair<long long,long long>
#define F first
#define S second
#define bug cout << endl << " .....here!...." << endl;
//#pragma GCC optimize("O3")
//#define Time (double)clock() / CLOCKS_PER_SEC <= 0.95
//using namespace __gnu_cxx;
//using namespace __gnu_pbds;
using namespace std;
ll cnt;
int main() {
CLOSE;
ll t;
cin>>t;
while (t--) {
ll l,r;
cin>>l>>r;
cnt=0;
while(r){
cnt+=(r-l);
r/=10;
l/=10;
}
cout<<cnt<<endl;
}
return 0;
}
6.礼品套装
情况:补题正确
题意:已知四个整数 x,y,a 和 b分别表示一共有x颗红色糖果和y颗蓝色糖果,一个礼品套装可以是a
粒红色糖果和b粒蓝色糖果,或者a粒蓝色糖果和b粒红色糖果。也就是x,y按照a,b还是按照b,a分,可以使得分的组数最大,求最大组数。
题解方法:
题解代码:
#include<bits/stdc++.h>
#define CLOSE ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define isd(c) ('0' <= (c) && (c) <= '9')
#define isa(c) ('a' <= (c) && (c) <= 'z')
#define isA(c) ('A' <= (c) && (c) <= 'Z')
#define mem(a, b) memset(a, b, sizeof a);
#define N 1000005
#define M 2000005
#define inf 0x3f3f3f3f
#define infll 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define PI acos(-1)
#define endl "\n"
#define pii pair<long long,long long>
#define F first
#define S second
#define bug cout << endl << " .....here!...." << endl;
#pragma GCC optimize("O3")
//#define Time (double)clock() / CLOCKS_PER_SEC <= 0.95
//using namespace __gnu_cxx;
//using namespace __gnu_pbds;
using namespace std;
ll x,y,a,b;
bool check(ll mid){
ll l=ceil((1.0*(x-b*mid)/(a-b)));
ll r=floor((1.0*(y-a*mid)/(b-a)));
l=max(l,(ll)0);
r=min(r,mid);
return l<=r;
}
void solve(){
cin>>x>>y>>a>>b;
if(a==b){
cout<<min(x/a,y/a)<<endl;
return ;
}
if(x>y){
swap(x,y);
}
if(a>b){
swap(a,b);
}
ll l=0,r=y;
while(l<r){
ll mid=(l+r+1)/2;
if(check(mid)){
l=mid;
}
else{
r=mid-1;
}
}
cout<<r<<endl;
}
int main() {
CLOSE;
ll t;
cin>>t;
while (t--) {
solve();
}
return 0;
}
四、赛事总结
1.注意一些细节的错误,例如变量用错了,头文件没写,手滑吧l打成1了等。
2.活跃思路,灵活运用方法,掌握做题策略。