A - Tit for Tat
题意:给你长为 n n n的数组, 你可以进行 k k k次操作。任意挑选两个元素进行一个加 1 1 1 一个减 1 1 1 操作,使数组变成字典序最小的不包含负数的数组
所以就是从前往后进行k次操作能减就减为0,不能减为0的话就减剩下来的 k k k,加一的话就在最后一个的元素加 k k k,保证字典序最小。
#include <iostream>
#define ll long long
using namespace std;
const int N = 1e6 + 9;
ll n, m, t, k, x, q, l, r, a[N], b[N], cnt, maxx;
multiset<ll> se;
int main(){
cin>>t;
while(t--) {
cin>>n>>k;
for(int i=1; i<=n; i++) {
cin>>a[i];
}
for(int i=1; i<n; i++) {
if(a[i]==0) continue;
if(!k) break;
if(a[i]<=k) {
a[n]+=a[i];
k-=a[i];
a[i]=0;//赋值为0的放在最后,比赛的时候差点直接交了
}else {
a[i]-=k;
a[n]+=k;
k=0;//一样
}
}
for(int i=1; i<=n; i++) {
cout<<a[i]<<" \n"[i==n];
}
}
return 0;
}
B - AGAGA XOOORRR
题意:给你个数组,判断能不能对两个相邻的元素进行异或,然后把异或结果放在这两数的位置,数组长度减一,使最后的数组只包含相同元素, 至少包含两个元素。
比赛的时候就是不知道剩下奇数个数的数组的时候怎么办
首先能想到
x
x
x ^
x
=
=
0
x==0
x==0,所以直接全部异或判断等不等于
0
0
0就好了结果WA了
然后就发现
x
x
x ^
x
x
x ^
x
x
x
=
=
x
==x
==x 那我们就分成几个前缀异或 反正他是相邻的进行异或
记录第一次出现前缀异或为0的时候
p
=
i
p=i
p=i,这个时候异或完是
a
[
n
]
=
=
5
a[n]==5
a[n]==5,那么在
p
p
p位置前面肯定有前缀异或为
5
5
5的,假如没有,那么说明是
x
x
x ^
x
=
=
0
x==0
x==0,但
a
[
n
]
=
=
5
a[n]==5
a[n]==5就不合法。
8
1 1 1 2 2 2 3 3 WA掉了
//假算法
#include <iostream>
#define ll long long
using namespace std;
const int N = 1e6 + 9;
ll n, m, t, p, q, a[N], x;
int main(){
cin>>t;
while(t--) {
cin>>n;
bool flag=0;
p=0;
for(int i=1; i<=n; i++) {
cin>>a[i];
a[i]^=a[i-1];
if(a[i]==0&&!p) p=i;//记录异或为0的时候
}
for(int i=1; i<=p; i++) if(a[i]==a[n]) flag=1;//判断前面是否有异或相同的结果
if(flag) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
C - Baby Ehab Partitions Again
题意:给你长度为 n n n的序列,问你能不能尽可能少删掉元素的个数,使这个序列不能分为两个序列之和相同的两个子序列
比赛的时候题意看错了以为是删掉最小的元素
题解就是裸的背包,删掉的元素只有一个
如果总和
s
u
m
sum
sum为奇数的时候不能平分直接cout 0
如果总和
s
u
m
sum
sum为偶数的时候并且能平分,那么我们删掉某个奇数就好了。但是没有奇数的话,我们就要找一个删掉了使他不能平分的偶数,我们把所有的数一直循环除
2
2
2 直到数列出现奇数,因为全是偶数,所有数各少一半不影响他能不能平分的结果,为了不循环,我们直接把所有数除去所有只2的最大公因子。这里都没想到。
#include <iostream>
#define ll long long
using namespace std;
ll n, m, q, a[5005], sum, dp[2000005], ans;
int main() {
cin>>n;
for(int i=1; i<=n; i++) {
cin>>a[i];
sum+=a[i];
}
if(sum%2==1) {
cout<<0<<endl;
return 0;
}
for(int i=1; i<=n; i++){
for(int j=sum/2; j>=a[i]; j--){
dp[j]=max(dp[j], dp[j-a[i]]+a[i]);
}
}
m=sum-dp[sum/2]*2;//两边之差为(sum-dp[sum/2])-dp[sum/2];
if(m!=0) cout<<0<<endl;//不能平分就说明两边之差不为0
else {
q=a[1];
for(int i=1; i<=n; i++) {
q=__gcd(q, a[i]);
}
for(int i=1; i<=n; i++) {
a[i]/=q;
if(a[i]%2==1) {
ans=i;
break;
}
}
cout<<1<<endl<<ans<<endl;
}
return 0;
}
D. Cut
bshd
赛后就不是很想看题了