Codeforces Round #767 (Div. 2)
Codeforces Round #767 (Div. 2)
A. Download More RAM
题意:现有\(k\) GB的RAM,每次可以运行所需RAM不大于现有RAM的软件,运行完后额外获得相应的RAM,问最终可以拥有最大RAM。
思路:贪心,优先找RAM需求小的软件即可。
/* Author: cyanine_farewell
* Time: 2022-01-22 22:35:03
**/
#include<bits/stdc++.h>
#define pb push_back
#define ll long long
#define fast ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 100010;
struct node{
int a,b;
} s[maxn];
bool cmp(node a,node b)
{
return a.a<b.a;
}
int main()
{
fast;
int T;
cin>>T;
while(T--)
{
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>s[i].a;
}
for(int i=1;i<=n;i++)
{
cin>>s[i].b;
}
sort(s+1,s+n+1,cmp);
for(int i=1;i<=n;i++)
{
if(s[i].a<=k)
{
k+=s[i].b;
}
}
cout<<k<<'\n';
}
return 0;
}
B. GCD Arrays
题意:给出\([l,r]\)的序列,可执行如下操作:选择序列中的两个数,删去这两个数并将他们的乘积加入序列。问能否在\(k\)次操作内,使得序列中所有数字的最大公因数不为\(1\)。
思路:贪心。尽量将所有数变为偶数,只需要判断序列中奇数个数是否不大于\(k\)即可。另外需要特判\(k=0\)的情况。
/* Author: cyanine_farewell
* Time: 2022-01-22 22:35:03
**/
#include<bits/stdc++.h>
#define pb push_back
#define ll long long
#define fast ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 100010;
int main()
{
fast;
int T;
cin>>T;
while(T--)
{
int l,r,k;
cin>>l>>r>>k;
if(k==0 && r==l)
{
if(l==1) cout<<"NO\n";
else cout<<"YES\n";
continue;
}
int num=(r-l)/2;
if(l%2==0 || r%2==0) num++;
if(k>=(r-l+1-num)) cout<<"YES\n";
else cout<<"NO\n";
}
return 0;
}
C. Meximum Array
题意:给出\(n\)个数,每次可以任意选取前\(k\)个数,求出其\(mex\)并加入结果序列中,重复操作,求字典序最大的结果。
思路:贪心。每次找到\(mex\)结果最大的最早出现位置。方法为:从左到右记录每个数字出现的位置,若当前初始位置为\(pos\),从小到大更新\(mex\)结果最大的最早出现位置\(temppos\),若后续不存在该数,\(mex\)结果即为该数,\(pos=temppos+1\)。每一轮结束后需要维护将每个数在\(pos\)前的位置记录删去。
/* Author: cyanine_farewell
* Time: 2022-01-22 22:35:03
**/
#include<bits/stdc++.h>
#define pb push_back
#define ll long long
#define fast ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 200010;
int n;
int a[maxn];
queue<int> v[maxn];
vector<int> ans;
int main()
{
fast;
int T;
cin>>T;
while(T--)
{
ans.clear();
cin>>n;
for(int i=0;i<=n;i++)
{
while(!v[i].empty()) v[i].pop();
}
for(int i=1;i<=n;i++)
{
cin>>a[i];
v[a[i]].push(i);
}
int pos=1;
while(pos<=n)
{
int temppos=pos;
// cout<<pos<<'\n';
for(int i=0;i<=n+1;i++)
{
while(!v[i].empty() && v[i].front()<pos) v[i].pop();
if(v[i].empty())
{
pos=temppos+1;
ans.pb(i);
break;
}
temppos=max(temppos,v[i].front());
}
}
cout<<ans.size()<<'\n';
for(int i=0;i<ans.size();i++)
{
cout<<ans[i]<<' ';
}
cout<<'\n';
}
return 0;
}
D. Peculiar Movie Preferences
题意:给出\(n\)个长度不大于\(3\)的字符串,问其子序列拼接而成的字符串是否回文串。
思路:分如下几种情况:
(1) 出现长度为\(1\)的字符串,结果为YES。
(2) 出现长度为\(3\)的字符串,需要判断字符串首尾是否相同,若存在,结果为YES。
(3) 剩下为组合的字符串,只需要考虑长度\(2+2,2+3,3+2,3+3\)四种情况即可,分类写即可。
/* Author: cyanine_farewell
* Time: 2022-01-22 22:35:03
**/
#include<bits/stdc++.h>
#define pb push_back
#define ll long long
#define fast ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 100010;
int n;
string s[maxn];
vector<string> v[4];
map<string,bool> pre;
int len[10];
int main()
{
fast;
int T;
cin>>T;
while(T--)
{
pre.clear();
for(int i=1;i<=3;i++)
{
v[i].clear();
}
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>s[i];
v[s[i].length()].pb(s[i]);
}
if(v[1].size()!=0)
{
cout<<"YES\n";
continue;
}
bool flag=0;
if(v[2].size()!=0)
{
for(int i=0;i<v[2].size();i++)
{
if(v[2][i][0]==v[2][i][1])
{
flag=1;
break;
}
}
if(flag)
{
cout<<"YES\n";
continue;
}
}
if(v[3].size()!=0)
{
for(int i=0;i<v[3].size();i++)
{
if(v[3][i][0]==v[3][i][2])
{
flag=1;
break;
}
}
if(flag)
{
cout<<"YES\n";
continue;
}
}
for(int i=1;i<=n;i++)
{
if(s[i].length()==3)
{
string s1="",s2="";
s1+=s[i][0];
s1+=s[i][1];
s2+=s[i][2];
s2+=s[i][1];
s1+=s[i][2];
s2+=s[i][0];
if(pre[s2])
{
flag=1;
break;
}
pre[s1]=1;
}
}
if(flag)
{
cout<<"YES\n";
continue;
}
pre.clear();
for(int i=1;i<=n;i++)
{
if(s[i].length()==3)
{
string s1="",s2="";
s1+=s[i][0];
s1+=s[i][1];
pre[s1]=1;
}
if(s[i].length()==2)
{
string s1="";
s1+=s[i][1];
s1+=s[i][0];
// cout<<s[i]<<' '<<s1<<'\n';
if(pre[s1])
{
flag=1;
break;
}
pre[s[i]]=1;
}
}
if(flag)
{
cout<<"YES\n";
continue;
}
pre.clear();
for(int i=1;i<=n;i++)
{
if(s[i].length()==3)
{
string s1="",s2="";
s2+=s[i][2];
s2+=s[i][1];
if(pre[s2])
{
flag=1;
break;
}
}
if(s[i].length()==2)
{
string s1="";
s1+=s[i][1];
s1+=s[i][0];
// cout<<s[i]<<' '<<s1<<'\n';
if(pre[s1])
{
flag=1;
break;
}
pre[s[i]]=1;
}
}
if(flag)
{
cout<<"YES\n";
continue;
}
cout<<"NO\n";
}
return 0;
}
E. Grid Xor
题意:给出\(n\cdot n\)的矩阵,每个数代表原矩阵周围四个数的异或和,求出原矩阵的异或和。
思路:任意确定第一行的值,后续的值按照\(b[i][j]=a[i-1][j]\bigoplus b[i-1][j-1]\bigoplus b[i-1][j+1]\bigoplus b[i-2][j]\)确认即可。无论矩阵如何最终的异或和是一样的。
/* Author: cyanine_farewell
* Time: 2022-01-22 22:35:03
**/
#include<bits/stdc++.h>
#define pb push_back
#define ll long long
#define fast ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 1010;
int a[maxn][maxn];
int b[maxn][maxn];
int main()
{
fast;
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
for(int i=0;i<=n+1;i++)
{
for(int j=0;j<=n+1;j++)
{
b[i][j]=0;
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cin>>a[i][j];
}
}
for(int i=1;i<=n;i++)
{
b[1][i]=675014;
}
for(int i=2;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
b[i][j]=a[i-1][j]^b[i-1][j-1]^b[i-1][j+1]^b[i-2][j];
}
}
int ans=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
ans^=b[i][j];
}
}
cout<<ans<<'\n';
}
return 0;
}
F. Game on Sum
题意:给定游戏轮数\(n\),必须得分轮数\(m\)与可选取最大值\(k\),每次Alice可以选择\(1-k\)的任意分数,Bob可以选择这次是加分还是减分,加分次数必须为\(m\)。问最终分数的期望。
思路1:设\(dp[i][j]\)为已选取\(i\)个数,加分次数为\(j\)分数的期望值。初始条件为:次数\(j=0\)时\(dp[i][j]=0\),\(i=j\)时\(dp[i][j]=i*k\)若Bob选择加分,则\(dp[i][j]=dp[i-1][j-1]+x\),若选择减分,则\(dp[i][j]=dp[i-1][j]-x\),那么最终期望为\(dp[i][j]=(dp[i-1][j-1]+dp[i-1][j])/2\)。
思路2:对于\(dp[n][m]\)其实有很多不必要的转移参与讨论。而\(dp[i][i]\)的值是可以很容易得到的,所以可以只讨论\(dp[i][i]\)到\(dp[n][m]\)的转移。对于每一个\(i\),\(dp[i][i]\)到\(dp[n][m]\)可以理解为在\(n-i\)次操作中加法次数为\(m-i\)的转移,考虑\(dp[i][i]\)不能影响后续的\(dp[i+1][i+1]\),因此操作数\(-1\),这个条件下的情况一共有\(C^{m-i}_{n-i-1}\)。计算贡献时由于每次转移需要\(/2\),因此最终的贡献需要\(/2^{n-i}\)。
/* Author: cyanine_farewell
* Time: 2022-01-22 22:35:03
**/
#include<bits/stdc++.h>
#define pb push_back
#define ll long long
#define fast ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 2010;
const int mod = 1e9+7;
ll f[maxn][maxn];
ll n,m,k;
ll Pow(ll a,ll b)
{
if(b==0) return 1;
if(b%2) return a*Pow(a,b-1)%mod;
ll tmp=Pow(a,b/2);
return tmp*tmp%mod;
}
int main()
{
fast;
int T;
cin>>T;
while(T--)
{
ll inv2=Pow(2,mod-2)%mod;
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
{
f[i][0]=0;
f[i][i]=k*i%mod;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(i==j) continue;
f[i][j]=(f[i-1][j-1]+f[i-1][j])%mod*inv2%mod;
}
}
cout<<f[n][m]<<'\n';
}
return 0;
}
/* Author: cyanine_farewell
* Time: 2022-01-22 22:35:03
**/
#include<bits/stdc++.h>
#define pb push_back
#define ll long long
#define fast ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 1000010;
const int mod = 1e9+7;
ll f[maxn];
ll n,m,k;
ll fac[maxn];
ll Pow(ll a,ll b)
{
if(b==0) return 1;
if(b%2) return a*Pow(a,b-1)%mod;
ll tmp=Pow(a,b/2);
return tmp*tmp%mod;
}
void init()
{
fac[0]=1;
for(int i=1;i<=1e6;i++)
{
fac[i]=fac[i-1]*i%mod;
}
}
ll C(ll n,ll m)
{
return fac[n]*Pow(fac[n-m]*fac[m]%mod,mod-2)%mod;
}
int main()
{
fast;
init();
int T;
cin>>T;
ll inv2=Pow(2,mod-2);
while(T--)
{
ll ans=0;
cin>>n>>m>>k;
if(n==m)
{
cout<<n*k%mod<<'\n';
continue;
}
for(int i=1;i<=m;i++)
{
ans=ans+C(n-i-1,m-i)*Pow(inv2,n-i)%mod*i%mod;
ans=ans%mod;
}
cout<<ans*k%mod<<'\n';
}
return 0;
}