CSP模拟6
保龄力,好开心
头一次考试,直接保龄,哎,还是太菜了。
A. 排序
考试时有思路,但是没有写下去,挺可惜的。
首先让我们求逆序对的个数,n<=1000,直接 O(n2) 求就行.
然后思考如何换,他要求我们换且必须换m次。这时想到,如何每一次交换,只是改变一对相对大小关系,不就行了。
后来发现不可行,通过只交换一次就达到目的不太可能,因为只交换一次只能保证一对相对关系;
而且如果改变一个逆序对,很难保证之前的逆序对还是逆序对。
那交换多次不就行了!
所以我们设 pos[i] 表示数值 i 在 a 排列中的位置(因为是排列,所以不用考虑重复),即 pos[a[i]]=i ;
然后进行交换 , 交换然后排序,这让我们不禁想到了冒泡排序,每一次内循环把当前数列最大值放到最后一位。
在这里可以用到类似的思想,依次进行操作 (pos[a[n]+1],n),(pos[a[n]+2],n) ........(pos[n],n)
这样我们发现最后的排列 b, 不仅把 n 放到了最后一位,还使之前的相对大小关系不变,而且把包含 n 的逆序对都用了。(可以认为把比a[n]大的数都砍了一,然后把n放在了最后,仔细想一下就可以了)
重复以上的操作,就会得到单调递增的数列。
/*#include <iostream> #include <cstdio> #include <vector> #include <algorithm>*/ #include <bits/stdc++.h> const int MAXN=1010; using namespace std; int n,m,tot; int a[MAXN],pos[MAXN],mp[MAXN]; struct node { int x,y; }; vector<node> ans; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9') {if(ch=='-') f=-1; ch=getchar();} while(ch>='0' & ch<='9') { x=x*10+ch-48; ch=getchar(); } return x*f; } void swp(int x,int y){ pos[a[x]]=y; pos[a[y]]=x; swap(a[x],a[y]); ans.push_back((node){x,y}); } int main() { n=read(); for(int i=1;i<=n;i++) { a[i]=read(); mp[i]=a[i]; } sort(mp+1,mp+n+1); int len=unique(mp+1,mp+n+1)-mp-1; for(int i=1;i<=n;i++) { a[i]=lower_bound(mp+1,mp+len+1,a[i])-mp; pos[a[i]]=i; } for(int i=1;i<=n;i++) { for(int j=1;j<i;j++) { if(a[j]>a[i]) { m++; } } } printf("%d\n",m); for(int i=n;i>=1;i--) { for(int j=a[i]+1;j<=i;j++) { swp(pos[j],i); } } for(int i=0;i<ans.size();i++) { printf("%d %d\n",ans[i].x,ans[i].y); } return 0; }
B. Xorum
emmmmm没有思路。
好像可以用神奇的性质做,但是正确性。。。
想要得到“1”,可以把 x 上其他位全部删掉,不就剩下 1 了吗;
至于怎么删掉,设当前 x 共有 a 位;
然后:
设y=x<<(a-1); 设z=x^y;设n=z+y;
设p=y+y; 设m=n^p; 设q=m^x;
手模一下就可以;
此时的q就是1<<(a+1);
再左移,和y进行异或,把y除了 a位的1 的其他位上的数消掉;
得到新y, 再x^新y,,就可以把x最高位的1消掉了;
#include <iostream> #include <cstdio> #include <vector> const int MAXN=100010; using namespace std; long long x,tot; struct node { long long x,y; }; char op[MAXN]; vector <node> ans; /*inline int read() { long long f=1,x=0; char ch=getchar(); while(ch<'0' && ch>'9') { if(ch=='-') { f=-1; } ch=getchar(); } while(ch>='0' && ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; }*/ long long work(long long x) { long long now=(x>>1),y=x; while(now) { ans.push_back((node){y,y}); op[tot++]='1'; y<<=1,now>>=1; } long long z=x^y; ans.push_back((node){x,y}) , op[tot++]='2'; long long n=z+y; ans.push_back((node){z,y}) , op[tot++]='1'; long long p=y+y; ans.push_back((node){y,y}) , op[tot++]='1'; long long m=n^p; ans.push_back((node){n,p}) , op[tot++]='2'; long long q=m^x; ans.push_back((node){m,x}) , op[tot++]='2'; while(y!=(y&-y)) { if(y&q) { ans.push_back((node){y,q}); y^=q; op[tot++]='2'; } ans.push_back((node){q,q}); op[tot++]='1'; q<<=1; } ans.push_back((node){x,y}) , op[tot++]='2'; return x^y; } int main() { scanf("%lld",&x); while(x!=1) { x=work(x); } printf("%lld\n",tot); for(int i=0;i<tot;i++) { if(op[i]=='1') { printf("1 %lld %lld\n",ans[i].x,ans[i].y); } if(op[i]=='2') { printf("2 %lld %lld\n",ans[i].x,ans[i].y); } } return 0; }

浙公网安备 33010602011771号