当前位置: 代码迷 >> 综合 >> HDU 5637 Transform (DFS+记忆化搜索+位运算)
  详细解决方案

HDU 5637 Transform (DFS+记忆化搜索+位运算)

热度:51   发布时间:2023-11-15 13:00:44.0

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5637

#include<bits/stdc++.h>
using namespace std;#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<ll,ll>
#define mk(x,y) make_pair(x,y)
const int mod=1e9+7;
const int maxn=2e5+9;
const int ub=1e6;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
/*
题目大意:给定s和t,和一个序列,
每次可以选择把s变为s^x,x是序列中的数字,
也可以把s上的一个位翻转,给定若干个s和t,
输出最后的结果即:sigma i*ans(i),ans(i)是
把第i个序对实现转换所需的最小次数。题目分析:根据异或的性质不难发现每个数最多只要选择一次,
对于每个序对,用dfs搜索,记忆化进行优化处理,开二维数组记录
已经搜索过的状态,(对于S,可以花二进制数中的1的次数进行反转,也可以挑选一个数
异或处理,这样进行搜索。)
*/
int n,m,x,y;
ll ans;
int a[20],cnt[maxn][20];
int bitcnt(int x){int ret=0;while(x) x-=x&-x,ret++;return ret; }
int dfs(int S,int pos){if(S==0) return 0;if(cnt[S][pos]) return cnt[S][pos];int ret=bitcnt(S);rep(i,pos,n) ret=min(ret,dfs(S^a[i],i+1)+1);return cnt[S][pos]=ret;
}
int main(){int t;scanf("%d",&t);while(t--){mst(cnt,0),ans=0;///初始化scanf("%d%d",&n,&m);rep(i,0,n) scanf("%d",&a[i]);rep(i,1,m+1){scanf("%d%d",&x,&y);///ans=(ans+1LL*i*dfs(x^y,0)%mod)%mod;}printf("%lld\n",ans);}return 0;
}