Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 899 Accepted Submission(s): 345 Problem Description A list of n integers are given. For an integer x you can do the following operations:
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:
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 \to 4$ (2 operations): $3 \to 7 \to 4$ $1 \to 2$ (1 operation): $1 \oplus 3 = 2$ $3 \to 9$ (2 operations): $3 \to 1 \to 9$
Source
Recommend wange2014 | We have carefully selected several similar problems for you: 6460 6459 6458 6457 6456
|
思路参考自:https://blog.csdn.net/loveyou11111111/article/details/50811153
谢谢大神了!!
题意:
给出nn个整数, 对于一个整数xx, 你可以做如下的操作若干次:
令x的二进制,你可以翻转其中一个位.
令y是给出的其中一个整数, 你可以把x变为x⊕y, 其中\⊕表示位运算里面的异或操作.
现在有若干整数对(S, T), 对于每对整数你需要找出从S变成T的最小操作次数.
分析:
考虑到第一种操作是将某一位取反,而第二种操作是抑或一个数。
显然第一种操作也是可以通过抑或一个数得到的。比如:第i位取反,相当于抑或(1<<i)这个数。于是就将n个数扩大到n+17就可以了,因为100000最多17位。
此外如果p^a^b^c...=q的话,那么a^b^c...=p^q。于是,只需要求出p^q至少需要几个数抑或而成就可以了。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5;
int n,m;
int a[N],dis[N];
bool vis[N];
void bfs()
{
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
queue<int> q;
q.push(0);
vis[0]=1;
dis[0]=0;
while(!q.empty()){
int t=q.front();
q.pop();
for(int i=0;i<n;i++){
int v=t^a[i];
if(dis[v]>dis[t]+1)dis[v]=dis[t]+1;
if(!vis[v]){
vis[v]=1;
q.push(v);
}
}
}
}
int main()
{
int T;
//cout<<(1<<16)<<endl;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)scanf("%d",&a[i]);
for(int i=0;i<17;i++)a[i+n]=(1<<i);
n+=17;
bfs();
ll ans=0;
for(int i=1;i<=m;i++){
int s,t;
scanf("%d%d",&s,&t);
//cout<<dis[s^t]<<endl;
ans=(ans+(ll)i*dis[s^t]%mod)%mod;
}
cout<<ans<<endl;
}
return 0;
}