比赛信息页 封面原图 画师スだち
说实话这场打完还是有点小价值的
A - Clearance Sale
题意
买东西买二送一,现在买了m个,问一共能得到多少个
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
void solve()
{
int n;
cin>>n;
cout<<n+n/2<<endl;
}
int main()
{
int T=1;
//scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}
B - Let Me Eat Cake!
题意
两个人分别有a,b( 1 ≤ a , b ≤ 100 1\leq a,b\leq 100 1≤a,b≤100)个蛋糕,只要两人蛋糕数不一样你就要吃掉多的那个人一半的蛋糕,问最终你吃了多少个
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
void solve()
{
int a,b;
scanf("%d%d",&a,&b);
int cnt=0;
while(a!=b)
{
if(a>b)
{
cnt+=a-a/2;
a/=2;
}
else
{
cnt+=b-b/2;
b/=2;
}
}
printf("%d\n",cnt);
}
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}
C - FightBots
题意
两个机器人,ALice的初始在 ( 0 , 0 ) (0,0) (0,0)的位置,Bob的初始在 ( x , y ) (x,y) (x,y)的位置,Alice的行动指令已经给你了,问Bob能不能在同样的步数下最后能与Alice相遇
思路
模拟Alice的行动指令算出最后她在什么位置,跟Bob的初始位置算曼哈顿距离,不大于n的话就要看与n的差值,是偶数就是Yes,否则全部都是No
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
void solve()
{
int n,x,y;
cin>>n>>x>>y;
pii Alice={0,0};
string cmd;
cin>>cmd;
for (int i = 0; i < n; i++)
{
if (cmd[i]=='L')
{
Alice.first--;
}
else if (cmd[i]=='R')
{
Alice.first++;
}
else if (cmd[i]=='U')
{
Alice.second++;
}
else if (cmd[i]=='D')
{
Alice.second--;
}
}
// printf("%d %d\n",Alice.first,Alice.second);
int dis=abs(Alice.first-x)+abs(Alice.second-y);
if(dis<=n and (n-dis)%2==0)
{
cout<<"YES\n";
}
else
{
cout<<"NO\n";
}
}
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}
D - The Undisappearance
题意
给你一个只包含 1 , 2 , 3 1,2,3 1,2,3的数组,你可以选择一个长度最大为 k k k的区间进行一次操作,在这个区间内所有数都+1,然后把4变成1,问有多少种变法可以保证变后的数组当中 1 , 2 , 3 1,2,3 1,2,3都至少出现过一次
思路
我们反向思考,考虑哪些子串变完之后会导致原数组缺数字,那就得把原数组中某一个数字全部囊括进来,好要保证这个区间内没有会变成这个数字的存在
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
void solve()
{
int n;
scanf("%d",&n);
vector<int> a(n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
ll ans=(ll)n*(n+1)/2;
for(int x:{1,2,3})
{
int dont_want=x-1;
if(dont_want==0)
{
dont_want=3;
}
ll subbable=0;
bool will_replace=false;
ll left=n;
ll right=0;
for(ll i=0;i<n;i++)
{
if(a[i]==x)
{
left=min(i,left);
right=i;
}
}
for(int i=left;i<right;i++)
{
if(a[i]==dont_want)
{
will_replace=true;
break;
}
}
if(will_replace==false)
{
ll l2=left,r2=right;
while(l2>=0&&a[l2]!=dont_want)
{
l2--;
}
while(r2<n&&a[r2]!=dont_want)
{
r2++;
}
ans-=(left-l2)*(r2-right);
}
}
printf("%lld\n",ans);
}
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}
E - Double Trouble
题意
给一个数组,进行k次操作使最后的元素和最小,每次操作可以任选一个数将其乘2
范围
1 ≤ n ≤ 2 ⋅ 1 0 5 1\leq n\leq 2\cdot 10^5 1≤n≤2⋅105,前30分保证 1 ≤ k ≤ n 1\leq k\leq n 1≤k≤n,后面的保证 1 ≤ k ≤ 1 0 9 1\leq k\leq 10^9 1≤k≤109
思路
很容易能想到前30分的算法,那就是开一个优先队列然后直接把所有数放进去,取出来再放进去重复k次就行了
#include <bits/stdc++.h>
#define mod 1000000007
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
void solve()
{
ll n,k;
cin>>n>>k;
priority_queue<ll,vector<ll>,greater<ll>> pq;
ll sum=0;
for(ll i=0;i<n;i++)
{
ll x;
cin>>x;
sum+=x;
sum%=mod;
pq.push(x);
}
while(k--)
{
ll x=pq.top();
pq.pop();
sum+=x;
sum%=mod;
pq.push(2*x);
}
sum%=mod;
cout<<sum<<endl;
}
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}
但是后面k到1e9了怎么办呢?其实是一个倍增的过程,如果这个数组已经被拉平了,具体而言就是最小的和最大的差不到一倍了,后面的过程其实就是重复的,就是全部翻一倍再翻一倍永无止境,我们只需要计算翻了多少倍,最后的零头再单独计算一下即可。处理的时候因为要随时能取出最小的和最大的元素所以我们改用multiset
代码
#include <bits/stdc++.h>
#define mod 1000000007
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll qpow(ll a,ll b)
{
ll res=1;
while(b)
{
if(b&1)
{
res=res*a%mod;
}
a=a*a%mod;
b>>=1;
}
return res;
}
void solve()
{
int n,k;
scanf("%d%d",&n,&k);
multiset<int> st;
ll sum=0;
for(int i=0;i<n;i++)
{
int x;
scanf("%d",&x);
sum+=x;
sum%=mod;
st.insert(x);
}
while(k>0)
{
if(2*(*st.begin())>=*st.rbegin())
{
break;
}
k--;
int now=*st.begin();
st.erase(st.begin());
st.insert(2*now);
sum+=now;
sum%=mod;
}
if(k>0)
{
int tmes=k/n;
int pw=qpow(2,tmes);
sum=(sum*1ll*pw)%mod;
k%=n;
while(k>0)
{
k--;
int now=*st.begin();
st.erase(st.begin());
now%=mod;
sum+=(now*1ll*pw)%mod;
sum%=mod;
}
}
printf("%lld\n",sum);
}
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}