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

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

34 (2 operations): 374

12 (1 operation): 13=2

39 (2 operations): 319


中文题意:
给出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[n]=(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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值