【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; } }
相关文章推荐
- C++中多线程的加锁机制
- C++ STL--stack/queue 的使用方法
- 关于C++的问题
- 1102. Invert a Binary Tree (25)
- 【hdu 5636】Shortest Path 中文题意&题解&代码(C++)
- C++模板归并排序
- C/C++中的位运算(下)
- 2.C语言数据类型
- 【hdu 5635】LCP Array 中文题意&题解&代码(C++)
- C++ 知识点备忘
- C++模板插入排序
- Effictive C++笔记
- C/C++中的位运算(上)
- 深入学习C++.2016_3_7
- Cpp--拷贝构造函数
- 九度OJ 1207:质因数的个数
- new................未完待续
- C语言实现大数据除法
- C++内存布局(下)
- c++编译器对多态的实现原理总结