Codeforces Round #838 (Div. 2) A-D
A. Divide and Conquer
题解:
题意为给你n个数,要使n个数的和变为偶数,一次操作可以令,求最少让n个数的和为偶数的操作次数。
若初始状态n个数的和为偶数,则无需再操作,否则,此时为奇数,每次进行一次操作的话,会减去,若为奇数的话,sum便会变为偶数。对于每个数,
若为偶数,则每次进行/2的操作,寻找变为奇数的情况的操作次数,即sum减去奇数的操作次数。
若为奇数,则每次进行/2的操作,寻找变为偶数的情况(变为0)的操作次数,即sum减去奇数的操作次数。
然后对所有的操作次数进行比较,答案为最小值
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6;
int a[N],b[N],n,m,x,y,z,t,k,q;
int ans,res;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T=1;
cin>>T;
while(T--)
{
cin>>n;
int sum=0;
for(int i=1; i<=n; i++)
{
cin>>a[i];
sum+=a[i];
}
if(sum%2==0)
{
cout<<0<<"\n";
continue;
}
int ans=1e9;
for(int i=1; i<=n; i++)
{
int res = 0;
if(a[i] % 2 == 0)
{
while(a[i] % 2 == 0)
{
res ++;
a[i] /= 2;
}
}
else
{
while(a[i] & 1)
{
a[i] /= 2;
res ++;
}
}
ans = min(ans, res);
}
cout<<ans<<"\n";
}
return 0;
}
B. Make Array Good
题解:
题意为给你n个数,要求使任意两个i,j,(1<=i,j<=n),使,
即任意两个数中最大值能够整除最小值,一次操作能够使
求操作次数和每次操作的过程,需要保证操作次数在n次以内。
先排序,然后从第二个开始依次检查是否是前一个的倍数,若不是倍数,则令,然后此时的一定变为的倍数,依次操作,
最终这个n个数一定满足上述条件。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6;
int n,m,x,y,z,t,k,q;
int ans,res;
struct MM
{
int a,b;
};
bool cmp(MM aa,MM bb)
{
return aa.a<bb.a;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T=1;
cin>>T;
while(T--)
{
cin>>n;
int sum=0;
MM xy[n+10];
for(int i=1; i<=n; i++)
{
cin>>xy[i].a;
xy[i].b=i;
}
sort(xy+1,xy+n+1,cmp);
vector<pair<int,int> >v;
for(int i=2;i<=n;i++)
{
if(xy[i].a%xy[i-1].a==0)
continue;
v.push_back({xy[i].b,xy[i-1].a-xy[i].a%xy[i-1].a});
xy[i].a+=xy[i-1].a-xy[i].a%xy[i-1].a;
}
cout<<v.size()<<"\n";
for(auto [x,y]:v)
{
cout<<x<<" "<<y<<"\n";
}
}
return 0;
}
C. Binary Strings are Fun
题意:
给你长度为n的01字符串,求他的每个前缀串的“扩展良好串”的个数,
“扩展良好串”意思是对原串a,扩展串b来说,,
且对于每个奇数i,等于前i个数的中位数(中位数是前i个数拍好序之后中间的那个数)
观察得到,当i为奇数时,每个都固定了,则现在需要求解i等于偶数的时候能填的情况,
当i为奇数时,若时,即前i个数的中位数为,且前i+2个数的中位数也为,现考虑
填什么,发现无论填什么,因为,则保证前i+2个数的中位数一定为 ,
此时可填0或1,有两种情况。
若时,即前i个数的中位数为,且前i+2个数的中位数为,现考虑
填什么,发现只有时,才能保证前i+2个数的中位数为,
则此时,只有一种情况。
综上,依次计算字符串前缀和能组成的字符串即可
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6;
int n,m,x,y,z,t,k,q;
int ans,res;
string s;
typedef long long ll;
const ll MOD=998244353;
ll quickpow(ll a,ll b)
{
ll sum=1;
while(b)
{
if(b&1)
sum=sum*a%MOD;
a=a*a%MOD;
b>>=1;
}
return sum;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T=1;
cin>>T;
while(T--)
{
int ans=0
char ch = '?';
int nnn = 0;
cin>>n;
cin>>s;
s=" "+s;
for(int i = 1; i <= n; i++)
{
if(s[i] == ch)
{
nnn ++;
continue;
}
ch = s[i];
ans = (ans + (quickpow(2, nnn) - 1)) % MOD;
nnn = 1;
}
cout<<(ans + (quickpow(2, nnn) - 1)) % MOD<<"\n";
}
return 0;
}
D. GCD Queries
题解:
这里有一个长度为 n 的 [0...n−1] 的排列 a
你可以最多询问 2∗n 次,每次给出两个数字 x,y ,程序会给你的值。
最后请输出 x,y 使得 中有一个是0
当n=2时,x=1,y=2
当n>2时,还是令x=1,y=2,
枚举i,(3<=i<=n),每次询问(x,i)和(y,i)
若,则排除第i个数为0,
因为若第i个数为0,则
而,则若第i个数必不为0
若,不妨设,
且令,此时可能为0,而必不为0,
若等于0,则,,而,则矛盾
故必不为0,此时,,
可能为0,则用来替换
最后输出x和y即可
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e6;
int n,m,x,y,z,t,k,q;
int ans,res;
string s;
signed main()
{
int T=1;
cin>>T;
while(T--)
{
cin>>n;
x=1,y=2;
int ax,ay;
if(n==2)
{
cout<<"! "<<1<<" "<<2<<endl;
cin>>ans;
continue;
}
for(int i=3;i<=n;i++)
{
cout<<"? "<<x<<" "<<i<<endl;
cin>>ax;
cout<<"? "<<y<<" "<<i<<endl;
cin>>ay;
if(ax==ay)continue;
else
{
if(ax<ay)
{
x=i;
}
else
{
y=i;
}
}
}
cout<<"! "<<x<<" "<<y<<endl;
cin>>ans;
}
return 0;
}