A.MEXanized Array
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=210;
int a[N];
int n,k,x;
void solve() {
cin>>n>>k>>x;
if(x<k-1) {
cout<<-1<<endl;
return;
}
if(n<k) {
cout<<-1<<endl;
return;
}
for(int i=0; i<k; i++) {
a[i]=i;
}
if(x==k) {
for(int i=k; i<n; i++) {
a[i]=k-1;
}
}
else{
for(int i=k;i<n;i++){
a[i]=x;
}
}
// for(int i=0;i<n;i++) cout<<a[i]<<' ';
// cout<<endl;
int sum=0;
for(int i=0;i<n;i++) sum+=a[i];
cout<<sum<<endl;
}
int main() {
int t=1;
cin>>t;
while(t--) {
solve();
}
return 0;
}
B.Friendly Arrays
异或==>按位异或,看其二进制每一位
二进制每一位要么为0,要么为1
如果要最大的话,我们尽可能让原本为1的继续保持为1,让原本为0的变成1
如果要最小的话,我们尽可能让原本为0的继续保持为0,让原本为1的变成0
现在可以让每一个a[i]或上b[j],b[j]可以任意选,由于是或,所以只要某一个b[j]某一位上是1,那么a[1]到a[n]的这一位必定为1,那么最后将a[1]到a[n]异或起来,那么这一位的结果就是n个1异或
当n为奇数的时候,这一位就为1,那么这一位只会不变或者增大(只有01两种情况),所以我们需要更多的位都能为1,所以或上所有的b[j],因为当b[j]某一位为0时,由于是或,所以对结果没影响,当某一位为1时,那么最后所有a[i]异或得到的结果的该位肯定是1,这样得到的值就是最大的,一个b[j]都不或得到的结果就是最小的
当n为偶数的时候,这一位为0,那么这一位只会不变或减小,所以如果要求最小值的话,那么就或上所有的b[j],要求最大值的话,那么就一个b[j]或
由此,最终最大值和最小值只在两种情况中取到,即对于每一个a[i],或上所有的b[j],然后全部的a[i]异或起来和对于每一个a[i],一个b[j]也不或上,然后全部的a[i]异或起来
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#define endl '\n'
using namespace std;
const int N=2e5+10;
int a[N],b[N];
int n,m;
void solve() {
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
int tmp=0;
for(int i=1;i<=m;i++){
cin>>b[i];
tmp|=b[i];
}
int x=0,y=0;
for(int i=1;i<=n;i++){
x^=a[i];
y^=(a[i]|tmp);
}
if(x>y) swap(x,y);
cout<<x<<' '<<y<<endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t=1;
cin>>t;
while(t--) {
solve();
}
return 0;
}
C.Colorful Table
可以发现,二维数组b是关于y=x对称的,包含所有数字x的矩形一定是一个正方形
包含小数字的正方形一定包含大数字的正方形
只要从大到小枚举颜色,找到它的最小下标以及最大下标,然后以最小下标和最大小标作为一条边组成的正方形即为包含该数字的正方形
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#define endl '\n'
//#define int long long
using namespace std;
int n,k;
void solve() {
cin>>n>>k;
vector<vector<int>>e(k+1);
vector<int>ans(k+1);
for(int i=1;i<=n;i++) {
int x;
cin>>x;
e[x].push_back(i);
}
int t1=2e9,t2=0;
for(int i=k;i>=1;i--){
if(e[i].size()==0) continue;
for(auto v:e[i]){
t1=min(t1,v);
t2=max(t2,v);
}
ans[i]=2*(t2-t1+1);
}
for(int i=1;i<=k;i++) cout<<ans[i]<<' ';
cout<<endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t=1;
cin>>t;
while(t--) {
solve();
}
return 0;
}
D.Prefix Purchase
原本思路:
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#define endl '\n'
//#define int long long
using namespace std;
const int N=2e5+10;
int a[N];
int n,k;
void solve() {
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
cin>>k;
int maxn=0;
int maxi=0;
for(int i=1;i<=n;i++){
int x=k/a[i];
if(x>=maxn){
maxn=x;
maxi=i;
}
}
if(k%a[maxi]==0){
for(int i=1;i<=maxi;i++) cout<<maxn<<' ';
for(int i=maxi+1;i<=n;i++) cout<<0<<' ';
cout<<endl;
}
else{
int idx=maxi;
for(int i=maxi+1;i<=n;i++){
if(a[maxi]+k%a[maxi]>=a[i]) idx=i;
}
for(int i=1;i<=maxi;i++) cout<<maxn<<' ';
for(int i=maxi+1;i<=idx;i++) cout<<1<<' ';
for(int i=idx+1;i<=n;i++) cout<<0<<' ';
cout<<endl;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t=1;
cin>>t;
while(t--) {
solve();
}
return 0;
}
发现有一个明显的问题:最后可能分出去的m*a[maxi]+k%a[maxi]中m可能不是1,那么该思路崩盘了
参考CodeTON Round 6 (Div. 1 + Div. 2, Rated, Prizes!) (A-D)_happychaoss的博客-CSDN博客
贪心
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#define endl '\n'
#define int long long
using namespace std;
const int N=2e5+10;
int a[N];
int n,k;
void solve() {
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
cin>>k;
//维护后缀最小值
for(int i=n-1;i>=1;i--) a[i]=min(a[i],a[i+1]);
vector<int>ans(n+1,0);
ans[1]=k/a[1];
int left=k-ans[1]*a[1];//剩下的硬币的数量
int cnt=k/a[1];//加的次数
for(int i=2;i<=n;i++){
int diff=a[i]-a[i-1];
if(diff==0) ans[i]=ans[i-1];
else{
cnt=min(cnt,left/diff);
left-=cnt*diff;
ans[i]=cnt;
if(cnt==0) break;
}
}
for(int i=1;i<=n;i++) cout<<ans[i]<<' ';
cout<<endl;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t=1;
cin>>t;
while(t--) {
solve();
}
return 0;
}