标签:
题意:给出n个数,n个数两两异或后的最后一个bit位k,求所有2^k的和。
比赛的时候递归写挂了。。。。痛心啊。。。后来看了半天结果把一个数组移到函数体里就1a了(递归的时候覆盖了。。。)T_T。
思路是这样的:如果最后一位不相同,那么他们异或结果的最后一位与二者最后一位较低的相同,那么把这些数字按最后一位的位置分为若干组,然后不同组可以直接相乘。相同组因为最后一位相同,所以异或的结果与最后一位无关,把最后一位去掉然后递归处理这一组。因为一共有30位,数组长度为n,复杂度大概是O(30*n)。
#include<iostream> #include<map> #include<algorithm> #include<cstdio> #include<cstring> #include<cstdlib> #include<vector> #include<queue> #include<stack> #include<functional> #define pb push_back using namespace std; typedef long long ll; const int maxv=5e4+40; const ll mod=998244353; int T,cas=0; ll a[maxv]; int n; vector<ll> nums; ll work(vector<ll> b){ vector<ll> bucket[32]; bool flag=0; for(int i=0;i<b.size();i++){ int p; if(b[i]){ p=__builtin_ffs(b[i])-1; flag=1; } else p=31; bucket[p].pb(b[i]); } if(!flag) return 0; ll ans=0; for(int i=0;i<32;i++){ for(int j=i+1;j<32;j++){ if(bucket[i].size()&&bucket[j].size()){ ans=(ans+(1ll<<(i))*bucket[i].size()%mod*bucket[j].size()%mod)%mod; } } } for(int i=0;i<31;i++){ if(bucket[i].size()){ for(int j=0;j<bucket[i].size();j++){ int p=__builtin_ffs(bucket[i][j])-1; bucket[i][j]^=1ll<<p; } ans=(work(bucket[i])+ans)%mod; } } return ans; } int main(){ cin>>T; while(T--){ cin>>n; nums.clear(); for(int i=0;i<n;i++) scanf("%lld",&a[i]); for(int i=0;i<n;i++) nums.pb(a[i]); printf("Case #%d: %lld\n",++cas,work(nums)*2); } return 0; }
标签:
原文地址:http://www.cnblogs.com/Cw-trip/p/4574194.html