1、两个长度为$n$的数组$a,b$,$0 leq a_{i} <2^{30}$。$b_{i}=-1$或者$b_{i}$为除$a_{i}$外其他数字的抑或值。现在给定$b$,如果不存在$a$,返回-1.否则输出$a$数组所有数字和的最小值。
思路:一位一位考虑。当前考虑第$k$位。对于所有不知道的数字将它们看做一个数字0或者1。现在就是一个全是01的数组$c$,那么$c_{i}$^$c_{j}$=$A_{i}$^$A_{j}$。其中$A_{i}=(a_{i}$>>$k)$&1.然后假定$A_{0}=$0或者1进行判断即可。
#include <stdio.h> #include <string.h> #include <string> #include <iostream> #include <vector> #include <set> #include <map> #include <queue> #include <algorithm> #include <stack> #include <assert.h> using namespace std; const int N=44; int n; vector<pair<int,int> > g[N]; int a[N],m; int b[N]; int c[N]; int dfs(int t) { for(int i=0;i<(int)g[t].size();++i) { int v=g[t][i].first; int w=g[t][i].second; if(b[v]==-1) { b[v]=w^b[t]; if(!dfs(v)) return 0; } else if(b[v]!=(w^b[t])) return 0; } return 1; } int get() { for(int i=0;i<m;++i) g[i].clear(); for(int i=0;i<m;++i) { for(int j=i+1;j<m;++j) { g[i].push_back(make_pair(j,a[i]^a[j])); g[j].push_back(make_pair(i,a[i]^a[j])); } } int ans=m+1; for(int i=0;i<2;++i) { memset(b,-1,sizeof(b)); b[0]=i; if(!dfs(0)) return -1; int all=0; for(int i=0;i<m;++i) all^=b[i]; int ok=1; for(int i=0;i<m&&ok;++i) { if(a[i]!=(all^b[i])) ok=0; } if(!ok) continue; int tmp=0; for(int i=0;i<m;++i) tmp+=b[i]; if(ans>tmp) ans=tmp; } if(ans==m+1) ans=-1; return ans; } int cal() { m=0; int k=0; for(int i=0;i<n;++i) { if(c[i]==-1) k=1; else a[m++]=c[i]; } if(k) { ++m; a[m-1]=0; int p0=get(); a[m-1]=1; int p1=get(); if(p0==-1) { if(p1==-1) return -1; return p1; } else { if(p1==-1) return p0; return min(p0,p1); } } else { return get(); } } class OthersXor { public: long long minSum(vector<int> x) { n=(int)x.size(); long long sum=0; for(int i=0;i<30;++i) { for(int j=0;j<n;++j) { if(x[j]==-1) c[j]=-1; else c[j]=(x[j]>>i)&1; } int p=cal(); if(p==-1) return -1; sum+=(1ll<<i)*p; } return sum; } };
2、一个$N$个节点的有向图。给出$m$个数对$(a_{0},b_{0}),(a_{1},b_{1})...(a_{m-1},b_{m-1})$。两个节点$X,Y$有边当且仅当存在一个数对$(a_{i},b_{i})$使得$a_{i}$可整除$X$且$b_{i}$可整除$Y$。给定起点$s$终点$t$,求最短路。
思路:将数对看做节点。第$i$个节点可以向第$j$个节点连边当且仅当$lcm(b_{i},a_{j})leq N$。
#include <stdio.h> #include <string.h> #include <string> #include <iostream> #include <vector> #include <set> #include <map> #include <queue> #include <algorithm> #include <stack> #include <assert.h> using namespace std; vector<int> g[1005]; int n; int s,t; queue<int> Q; int f[1005]; int bfs() { memset(f,-1,sizeof(f)); f[0]=0; Q.push(0); while(!Q.empty()) { int u=Q.front(); Q.pop(); for(int i=0;i<(int)g[u].size();++i) { int v=g[u][i]; if(f[v]==-1) { f[v]=f[u]+1; Q.push(v); } } } if(f[t]!=-1) return f[t]-1; return f[t]; } int gcd(int a,int b) { return !b?a:gcd(b,a%b); } class FromToDivisible { public: int shortest(int N,int S,int T,vector<int> a,vector<int> b) { n=(int)a.size(); s=0; t=n+1; for(int i=0;i<n;++i) for(int j=0;j<n;++j) if(i!=j) { long long tmp=1ll*b[i]/gcd(b[i],a[j])*a[j]; if(tmp<=N) { g[i+1].push_back(j+1); } } for(int i=0;i<n;++i) { if(S%a[i]==0) g[0].push_back(i+1); if(T%b[i]==0) g[i+1].push_back(t); } return bfs(); } };