1000~1500cf构造题
B
//异或性质+题目给的2n个数(1~n,出现2次)分割为两组
//分析要使得异或结果两个数组,要结合性质2,性质二说明在第
//一个数组中,某个数子出现0,1,2次;对称的第二个数组就会出现2,1,0次
//结合异或性质,维持0,1,2平和就好;
`#include [HTML_REMOVED]
using namespace std;
void solve(){
int n,k;
cin>>n>>k;
set[HTML_REMOVED] g1,g0,g2;
map[HTML_REMOVED] ma;
for(int i=0;i[HTML_REMOVED]>num;
ma[num]++;
}
int eat;
for(int i=0;i[HTML_REMOVED]>eat;
for(int i=1;i<=n;i++){
if(ma[i]==1){
g1.insert(i);
}else if(ma[i]==2){
g2.insert(i);
}else{
g0.insert(i);
}
}
//cout<<g1.size()<<"\n"<<g2.size()<<"\n"<<g0.size()<<"\n";
int y=0;
for(auto i:g2){
if(y<2*k){
cout<<i<<" "<<i<<" ";
y+=2;
}
}
for(auto i:g1){
if(y<2*k){
cout<<i<<" ";
y++;
}
}
cout<<"\n";
y=0;
for(auto i:g0){
if(y<2*k){
cout<<i<<" "<<i<<" ";
y+=2;
}
}
for(auto i:g1){
if(y<2*k){
cout<<i<<" ";
y++;
}
}
cout<<"\n";
}
int main(){
int t;
cin>>t;
while(t–){
solve();
}
}`
C
// 简单博弈,脑子模拟
`#include [HTML_REMOVED]
using namespace std;
typedef pair[HTML_REMOVED] pii;
void solve(){
int n;
cin>>n;
map[HTML_REMOVED] ma;
for(int i=1;i<=n;i){
int num;
cin>>num;
ma[num];
}
int b=0;
int cnt=0;
for(auto [num,s]:ma){
if(num!=b){
cout<<b<<”\n”;
return ;
}
if(cnt==1&&s==1){
cout<<b<<”\n”;
return ;
}
if(s==1){
cnt;
}
b;
}
cout<<b<<”\n”;
};
int main(){
int t;
cin>>t;
while(t–){
solve();
}
}`
C
`#include [HTML_REMOVED]
using namespace std;
typedef long long ll;
int n;
ll sum[501];
void init(){
for(int i=1;i<=500;i++){
sum[i]+=sum[i-1]+(ll)(2i-1)i;
}
}
void solve(){
cin>>n;
cout<<sum[n]<<" "<<2*n<<"\n";
for(int i=n;i>=1;i--){
for(int k=1;k<=2;k++){
cout<<k<<" "<<i<<" ";
for(int j=1;j<=n;j++) cout<<j<<" ";
cout<<"\n";
}
}
//cout<<"\n";
}
int main(){
int t;
cin>>t;
init();
while(t–){
solve();
}
}`
//咋感觉除了第一道题,其他都没思维呢
C
//这道题好难,研究了好久题解和代码。
//整理一下思路:首先这种题肯定要打表,把发现符合条件的组合都是1不在中间,2不可能在第三;
//同时贪心性的分析,在极端位置被线段经过的多;再观察表的性质排列顺序规则,发现每个元素可以往
//左或者右边填,优先往左;于是乎数列构造规则归纳完毕
//接着要完成第k个dfs,直接暴力显然超时,回想dfs全排列如何快速得到第k个序列,用的是阶乘!!
//此题是吗?不是,一个元素可以往左或者右,且不受其他影响,往二进制想,这里我给不出严格说明
//但是以小序列来证明归纳,123,一个元素0,两个元素2,三个元素4....
//代码:模仿洛谷 聪明的乖宝宝
`#include [HTML_REMOVED]
using namespace std;
typedef long long ll;
ll ans[200005];
int t;
int dfs(ll l,ll r,ll p,ll n,ll k){
if(p==n){//模拟填入数字
k–;
ans[l]=p;
if(k) return 0;
else return 1;
}
int md=(r-l);
int flag=0;
if(md>=60)//太大了直接当作放左边,不然爆ll
{
flag=0;
}else if(((ll)1<<(md-1))<k) flag=1;//小于k得放右边
if(flag){
ans[r]=p;
return dfs(l,r-1,p+1,n,k-((ll)1<<(md-1)));
}else{
ans[l]=p;
return dfs(l+1,r,p+1,n,k);//说明这个分割点太大
}
}
void solve(){
ll n,k;
cin>>n>>k;
int md=dfs(1,n,1,n,k);
if(md){
for(int i=1;i<=n;i++) cout<[HTML_REMOVED]>t;
while(t–){
solve();
}
}`