写了三个题结果C fst了O.0
A - Boboniu Likes to Color Balls
回文串,最多有球是一个奇数个。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{IO;int T;cin>>T;while(T--){int a,b,c,d;cin>>a>>b>>c>>d;int cnt=(a&1)+(b&1)+(c&1)+(d&1);if(cnt==0||cnt==1||cnt==4) cout<<"Yes"<<endl;//如果全是4个奇数可以用rgb换一个w,那么就变成全是偶数个else if(cnt==2) cout<<"No"<<endl;else{if(a*b*c) cout<<"Yes"<<endl;else cout<<"No"<<endl;//说明rgb中有球的个数是0 不能换球}}return 0;
}
B - Boboniu Plays Chess
直接模拟,一行一行走,先走完最初所在的行,然后从第一行开始S型走
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=210;
int n,m;
int u,v;
bool st[N];
int main()
{IO;cin>>n>>m;cin>>u>>v;cout<<u<<" "<<v<<endl;st[u]=1;for(int i=1;i<=m;i++)if(i!=v) cout<<u<<" "<<i<<endl;int v=m;for(int i=1;i<=n;i++){if(st[i]) continue;st[i]=1;if(v==m) {for(int j=m;j;j--)cout<<i<<" "<<j<<endl;v=1;}else{for(int j=1;j<=m;j++)cout<<i<<" "<<j<<endl;v=m;}}return 0;
}
C - Boboniu and Bit Operations
贪心的取cic_ici最小最终OR最小不正确。如果某一位必须是1,那么其他cic_ici的该位是否为1就不重要了。
最开始想用trie树实现贪心cic_ici,结果后来一想不正确,就随便写了个dp没想的过了???(结果还是被FST
原因还是上述贪心方法不正确。
FST代码——O(n3)O(n^3)O(n3)
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=210;
int a[N],b[N];
int n,m;
int f[N][N];
int main()
{IO;cin>>n>>m;for(int i=1;i<=n;i++) cin>>a[i];for(int i=1;i<=m;i++) cin>>b[i];memset(f,0x3f,sizeof f);for(int i=1;i<=m;i++) f[0][i]=0;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)for(int k=1;k<=j;k++) f[i][j]=min(f[i][j],f[i-1][j]|(a[i]&b[k]));cout<<f[n][m]<<endl;return 0;
}
正解是枚举答案。我也想过枚举答案可是不知道怎么判断答案是否复合tcl。
如果枚举答案kkk,那么对于每一个aia_iai都能找一个bjb_jbj使得a[i]&b[j]
二进制中1出现的位置答案中必须也出现,即(a[i]&b[j])|k==k
,一一判断即可
正解——O(29nm)O(2^9nm)O(29nm)
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<iostream>
#include<algorithm>
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N=210;
int a[N],b[N];
int n,m;
int main()
{IO;cin>>n>>m;for(int i=1;i<=n;i++) cin>>a[i];for(int i=1;i<=m;i++) cin>>b[i];for(int k=0;k<1<<9;k++){bool ok1=1;for(int i=1;i<=n;i++){bool ok2=0;for(int j=1;j<=m;j++)if(((a[i]&b[j])|k)==k){ok2=1;break;}if(!ok2){ok1=0;break;}}if(ok1) return cout<<k<<'\n',0;}
}
D - Boboniu Chats with Du
复制数组!!!
分析题目可以简化成如果ai<=ma_i<=mai<=m那么代价是111,如果ai>ma_i>mai>m代价是d+1d+1d+1很明显是一个01背包,不过数据范围。。。
从集合角度考虑:不妨让小于等于m的放在a[]
数组并逆序,大于m放在b[]
数组同样逆序,最终的答案一定是a[]
数组选出前i
个,从b[]
数组选出前j
个。因此我们可以枚举从b[]
数组选择了多少个,然后剩余的从a[]
数组选即可。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<iostream>
#include<algorithm>
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N=100010;
ll a[N],b[N];
int cnta,cntb;
int n,d;
ll m;
int main()
{IO;cin>>n>>d>>m;for(int i=1;i<=n;i++){ll x;cin>>x;if(x>m) b[++cntb]=x;else a[++cnta]=x;}sort(a+1,a+1+cnta);sort(b+1,b+1+cntb);reverse(a+1,a+1+cnta);reverse(b+1,b+1+cntb);for(int i=1;i<=cnta;i++) a[i]+=a[i-1];for(int i=cnta+1;i<=n;i++) a[i]=a[i-1];//这个地方非常dt 需要赋值一份for(int i=1;i<=cntb;i++) b[i]+=b[i-1];ll res=0;int cntm=min(cntb,(n+d)/(d+1));for(int k=0;k<=cntm;k++){//如果不进行上述复制操作 如果n-(d+1)*(k-1)-1>cnt a[n-(d+1)*(k-1)-1]=0 理论应该是所有a[cnta]ll now=b[k];if(k) now+=a[n-(d+1)*(k-1)-1];//如果不进行上述复制那么now+=a[min(cnta,n-(d+1)*(k-1)-1]else now+=a[n];//now+=a[cnta]res=max(res,now);}cout<<res<<endl;return 0;
}
emm~~看E群里面讨论的很难 随缘补吧。要加油哦!