A . Tit for Tat
传送门
题目大意:
给n个非负数,和最多k次修改,每次修改可以将不同下标的元素分别+1和-1,求修改后最小字典序的结果
思路:
因为就100个不超过的数,暴力,从左到右,每个元素减到0即可,同时k要大于0,while( a[i]>0 && k) a[i]--,k--;即可,不用想太多= =
B . AGAGA XOOORRR
传送门
题目大意:给n个非负数,可以将相邻的两个元素进行异或操作,然后用异或结果代替两个元素放入原位,最后剩余所有元素相等,且至少剩两个元素,。问这样的结果是否存在
思路:思维,异或前缀和
异或性质:交换律,结合律,前缀和,并且区间异或和只要两个端点异或就相当于“减”了
进入正题,举两个例子最后成立的情况有两种,假设最后全剩余5,如果剩余偶数的5,可以归并成(5,5),可以发现此时所有元素异或和为0,因为相等元素异或为0
如果剩余奇数的5,可以归并成(5,5 , 5),但是存在(5)的情况,(5,5 , 5)可以推到(5),但是反过来不行,可以发现最后异或的结果是剩余的元素,只要证明存在3个相同元素即可,第一个5异或和5,前两个5异或和为0,全部异或和为5,假设剩余元素为a,所以我们只要找到异或前缀和为a,0,a的情况即可,即在前n-1个前缀和里找a,0的情况就好了。
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0)
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define _rep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(x,y) memset(x,y,sizeof(x))
#define all(v) v.begin() , v.end()
#define pb(v) push_back(v)
#define INF 0x3f3f3f3f
#define int long long
#define lson p*2,l,mid
#define rson p*2+1,mid+1,r
typedef long long ll;
const int N =1e6+10;
const int mod = 1e9+7;
int a[N];
int n,k;
int sum[2010];//异或前缀和
bool solve()
{
int flag=0;
if( !sum[n] ) return true;//异或和为0,返回真
//处理最后剩余三个元素的情况
_for(i,1,n-1)
{
if( sum[i]==0 )
{
flag=i;//找到前两个异或和为0的点
}
}
int f=0;
//从前flag数中,找异或前缀和等于sum[n]的情况
_for(i,1,flag)
{
if( sum[i] == sum[n]) f=1;
}
if(f) return true;
return false;
}
signed main()
{
// freopen("data.txt","r",stdin);
IOS;
int T;
cin>>T;
while( T-- )
{
mst(sum,0);
cin>>n;
_for(i,1,n)
{
cin>>a[i];
sum[i] = sum[i-1] ^ a[i];//求异或前缀和
}
if( solve() ) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
C . Baby Ehab Partitions Again
传送门
题目大意:
一个序列包含n个非负数,问是否可以将其分任意为两段而不存在两段数值和相等的情况,可以删除一个数,问最小删的数是多少,不用删就输出0
思路:背包 / 暴力
第一眼暴力 ,但是写完线段树板子只剩10min了,直接放弃了QAQ,debug还要30min以上= =
正解,背包做法(没看出来T - T
裸的背包,设所有数总和为sum,dp[i]为容量为i的背包最多存的数值,最后看是否2 * dp[sum/2] == sum ?即可
删数可以证明删最小奇数。
假如存在两段数值和相等的情况,那么sum肯定为偶数,即去奇数后便无法划分为两段和的序列了。
进一步考虑,如果所有元素都为偶数,怎么删呢
将所有元素除以2,再删最小奇数,除以2后是等价的
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
#include <map>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0)
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define _rep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(x,y) memset(x,y,sizeof(x))
#define all(v) v.begin() , v.end()
#define pb(v) push_back(v)
#define INF 0x3f3f3f3f
#define lson p*2,l,mid
#define rson p*2+1,mid+1,r
typedef long long ll;
const int N =1e5+10;
int n;
int sum;
int a[N];
int dp[200005];
int flag;//是否全偶
int oddmin =INF;//最小奇数
int temp;
signed main()
{
//!!!
// freopen("data.txt","r",stdin);
//!!!
IOS;
cin>>n;
_for(i,1,n)
{
cin>>a[i];
sum += a[i];
if( a[i] & 1)
{
if( a[i] < oddmin)
{
oddmin = a[i];
temp = i;
}
}
}
//背包
_for(i,1,n)
{
for(int j=sum/2 ;j>=a[i] ;j--)
{
dp[j] = max(dp[j] , dp[j-a[i]] + a[i]);
}
}
if( sum - dp[sum/2] * 2) cout<<0<<endl;
else
{
if( oddmin < INF) cout<<1<<endl<<temp<<endl;
else//全偶的情况
{
int cnt=0;
while( oddmin>=INF )
{
for(int i=1 ;i<=n ;i++)
{
a[i] /=2;
if( a[i] & 1)
if( a[i] < oddmin)
{
oddmin = a[i];
temp = i;
}
}
cnt++;
}
cout<<1<<endl<<temp<<endl;
}
}
}