ZZUOJ 10509: xor运算统计

题目链接http://acm.zzu.edu.cn:8000/problem.php?id=10509

题目大意:给定n个正整数,a1 a2 ... an,从中选取k个数 , ai1 ai2 ai3 ... Aik,其中(1<=i1<i2<i3<...<ik<=n),u=ai1 ^ai2 ^ai3 ^... ^Aik,将异或和为u 的序列(i1,i2,...,ik)的个数记为f(u),求∑(f(u)*u) (枚举u从1到正无穷) ,由于数值可能非常大,输出对1000000007 取模后的余数(即结果mod 1000000007)。

解题思路:由于ai < 1e6,所以ai的二进制位最多有20位。对每一位来说,假设这一位有xi个1,那么如果要使这一位为1,只需要从xi中选出来奇数个1(假设有k1个),从n-xi中选出来剩余n-k1个零,而这样子的选择方案共有C(xi,1)C(n-xi, k - 1) + C(xi,3)C(n-xi, k - 3) + …… .现在来考虑这样子如何计算结果,假设现在有四个数1 2 3 7, 对应二进制001,010,011,111,从中选k=3个数,那么所有结果总共有

1^2^3 = 0, 1^2^7 = 4, 1^3^7 = 5, 2^3^7 = 6四个。那么显然答案应当是4+5+6。现在将4 5 6这三个数的二进制展开,得到:

4 = 0x1 + 0x2 + 1x4

5 = 1x1 + 0x2 + 1x4

6 = 0x1 + 2x1 + 1x4

到这儿大概已经能够发现,只需要将每一位可选的方案数目乘以其对应的2的幂,最后求和即是要求的答案。

大致过程:扩展gcd求逆元并记录1~1e6的逆元;对于每个xi,使用组合数递推公式C(n,k) = C(n, k - 1) * (n - k + 1) / k 求xi以及n-xi的组合数值,复杂度O(n);最后累加求和即是答案。

代码:

 1 const int maxn = 1e5 + 5;
 2 ll c[maxn], c1[maxn], inv[maxn];
 3 int n, k;
 4 int ti[20], a1[maxn];
 5 
 6 void ext_gcd(ll a, ll b, ll &d, ll &x, ll &y){
 7     if(b == 0){
 8         d = a; x = 1; y = 0;
 9     }
10     else{
11         ext_gcd(b, a % b, d, y, x); 
12         y -= x * (a / b);
13     }
14 }
15 int modinv(ll a){
16     ll x, y, d;
17     ext_gcd(a, -mod, d, x, y);
18     if(d < 0) x = -x;
19     return (x + mod) % mod;
20 }
21 void getinv(){
22     for(int i = 2; i <= 1e5; i++)
23         inv[i] = modinv(i);
24 }
25 void getcom(int x){
26     c[0] = c1[0] = 1; c[1] = x; c1[1] = n - x;
27     for(int i = 2; i <= x; i++) 
28         c[i] = c[i - 1] % mod * (x - i + 1) % mod * inv[i] % mod;
29     for(int i = 2; i <= n - x; i++)
30         c1[i] = c1[i - 1] % mod * (n - x - i + 1) % mod * inv[i] % mod;
31 }
32 void solve(){
33     getinv();
34     memset(ti, 0, sizeof(ti));
35     int mxcnt = 0;
36     for(int i = 1; i <= n; i++){
37         int x = a1[i], cnt = 0;
38         while(x){
39             ti[cnt++] += (x & 1);
40             x >>= 1;
41         }
42         mxcnt = max(mxcnt, cnt);
43     }
44     ll ans = 0;
45     for(int i = 0; i <= mxcnt; i++){
46         int x = ti[i], tm = 1 << i;
47         getcom(x);
48         for(int i = 1; i <= k; i += 2){
49             if(k - i > n - x || i > x) continue;
50             ans = ans + c[i] % mod * c1[k - i] % mod * tm % mod;
51             ans %= mod;
52         }
53     }
54     printf("%lld\n", ans);
55 }
56 int main(){
57     scanf("%d %d", &n, &k);
58     for(int i = 1; i <= n; i++)
59         scanf("%d", &a1[i]);
60     solve();
61 }

题目:

10509: xor运算统计

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 26  Solved: 5
[Submit][Status][Web Board]

Description

给定n个正整数,a1 a2 ... an,从中选取k个数 , ai1 ai2 ai3 ... Aik,其中(1<=i1<i2<i3<...<ik<=n),u=ai1 ^ai2 ^ai3 ^... ^Aik,将异或和为u 的序列(i1,i2,...,ik)的个数记为f(u),求∑(f(u)*u) (枚举u从1到正无穷) ,由于数值可能非常大,输出对1000000007 取模后的余数(即结果mod 1000000007)。

 

Input

第一行两个整数n和k (1<=n,k<=10^5)
第二行n个整数,表示a1 a2 ... An. (0<=ai<=10^6)

 

Output

输出一行一个整数,表示最后的答案.

 

Sample Input

4 2
1 1 2 3

Sample Output

11

HINT

 

Source

JXD

Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值