您的位置:首页 > 编程语言 > C语言/C++

【hdu 5637】Transform 中文题意&题解&代码(C++)

2016-03-07 21:02 531 查看

Transform

Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)

Problem Description

A list of n integers are given. For an integer x you can do the following operations:

let the binary representation of x be b31b30…b0⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯, you can flip one of the bits.

let y be an integer in the list, you can change x to x⊕y, where ⊕ means bitwise exclusive or operation.

There are several integer pairs (S,T). For each pair, you need to answer the minimum operations needed to change S to T.

Input

There are multiple test cases. The first line of input contains an integer T (T≤20), indicating the number of test cases. For each test case:

The first line contains two integer n and m (1≤n≤15,1≤m≤105) – the number of integers given and the number of queries. The next line contains n integers a1,a2,…,an (1≤ai≤105), separated by a space.

In the next m lines, each contains two integers si and ti (1≤si,ti≤105), denoting a query.

Output

For each test cases, output an integer S=(∑i=1mi⋅zi) mod (109+7), where zi is the answer for i-th query.

Sample Input

1

3 3

1 2 3

3 4

1 2

3 9

Sample Output

10

Hint

3→43 \to 4 (2 operations): 3→7→43 \to 7 \to 4

1→21 \to 2 (1 operation): 1⊕3=21 \oplus 3 = 2

3→93 \to 9 (2 operations): 3→1→93 \to 1 \to 9

中文题意:

给出n个数a1,a2,a3。。。。。an,然后给出m组询问,每组询问中有两个数x,y,对于x可以有两种操作,一种是让x xor ai ,另一种是将x的第i位翻转,即x xor (1< < i),问x最少几步操作可以等于y,然后将这m个解按题上要求的那个求和公式输出。

题解:

我们发现要求出x操作几步得到y,通过亦或的性质,就是求能有几步操作得到一个数W,使得 x xor W == y,即 W = x xor y ,而得到 W 只能通过选择一些 ai 或选择一些 (1 < < i)来达到,这就是一个很明显的背包dp了。

代码:

#include<iostream>
#include<algorithm>
#include<stdio.h>
#define maxn (131080)
using namespace std;
int x,y,a[50],n,m,T,dp[maxn*2];
long long ans=0;
int main()
{
long long mmod=1e9+7;
scanf("%d",&T);
while(T--)
{
ans=0;
scanf("%d%d",&n,&m);

for(int i=1;i<=n;i++)
scanf("%d",&a[i]);

for (int i=0;i<18;i++)
{
n++;
a
=(1<<i);
}

for (int i=0;i<=maxn;i++)
dp[i]=999999;
dp[0]=0;
//典型背包dp
for (int i=1;i<=n;i++)
for (int j=0;j<maxn;j++)
{
if ( dp[j]!=999999  )
dp[j^a[i]]=min(dp[j^a[i]],dp[j]+1);
}
for (int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
//注意要将这里想乘的两个数强转成long long
//因为虽然他们是两个int,但是是接近int最大值的int
//相乘之后有很大的可能性乘积大于int
ans=(ans+(long long)dp[x^y]*(long long)i)%mmod;
}
//      printf("%I64d",ans);
cout<<ans<<endl;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: