E
给出三个序列共n个元素,每个元素值为1~n且不重
一次可以把一个元素换到另一个序列中,求最少操作次数使得三个序列(可为空)分别排序后并在一起为1~n顺序
题解
(伪)神仙题
随便dp,依次考虑每个数放在那里
由于要保证最终的顺序,所以放的序列的编号要单调
f[i][0/1/2],第i个放在0/1/2的最小操作数
code
#include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #define fo(a,b,c) for (a=b; a<=c; a++) #define fd(a,b,c) for (a=b; a>=c; a--) #define min(a,b) (a<b?a:b) using namespace std; int a[200002]; int f[200002][3]; int n,n1,n2,n3,i,j,k,l,ans,Ans; int main() { // freopen("e.in","r",stdin); scanf("%d%d%d",&n1,&n2,&n3);n=n1+n2+n3; fo(i,1,n1) scanf("%d",&j),a[j]=0; fo(i,1,n2) scanf("%d",&j),a[j]=1; fo(i,1,n3) scanf("%d",&j),a[j]=2; memset(f,127,sizeof(f)); f[0][0]=f[0][1]=f[0][2]=0; fo(i,0,n-1) { fo(j,0,2) { fo(k,j,2) f[i+1][k]=min(f[i+1][k],f[i][j]+(k!=a[i+1])); } } printf("%d\n",min(min(f[n][0],f[n][1]),f[n][2])); }
F
n个数,求一个x(x<=2^30-1)使得每个ai xor x二进制下一的个数相同
ai<=2^30-1
题解
折半,每边15位
设n个数最终1的个数为x,i的前15位异或后1的个数为ci
那么后15位的个数分别为x-c1,x-c2,x-c3...x-cn
差分一下变成c1-c2,c2-c3,c3-c4...,刚好与前15位的差分c2-c1,c3-c2,c4-c3...成相反数关系
处理出一边的情况,把序列取反哈希后丢到map里,再枚举另一边判断即可
code
#include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <map> #define fo(a,b,c) for (a=b; a<=c; a++) #define fd(a,b,c) for (a=b; a>=c; a--) #define mod 1145141919810ll using namespace std; int a[101]; int b[101]; int n,i,j,k,l,x,s1,s2; map<long long,int> hs; map<long long,int> :: iterator I; long long s; int get(int x) { int s=0; while (x) { ++s; x^=x&-x; } return s; } int main() { // freopen("f.in","r",stdin); scanf("%d",&n); fo(i,1,n) scanf("%d",&a[i]),b[i]=a[i]&32767,a[i]=a[i]>>15; fo(x,0,32767) { s=1; fo(i,1,n) { s1=get(a[i]^x); if (i>1) s=(s*233+(s1-s2+233))%mod; s2=s1; } hs.insert(map<long long,int>::value_type(s,x)); } fo(x,0,32767) { s=1; fo(i,1,n) { s1=get(b[i]^x); if (i>1) s=(s*233+(s2-s1+233))%mod; s2=s1; } I=hs.find(s); if (I!=hs.end()) { printf("%d\n",(*I).second*32768+x); return 0; } } printf("-1\n"); }