codeforces 1557 C Moamen and XOR(递推、分类讨论)

这篇博客讲解了如何通过二进制分析将Codeforces 1557C题目的条件转化为000和111的组合,通过奇偶性分类讨论,确定与运算与异或运算结果的关系。涉及递推公式和快速幂算法,详细解析了解决此类问题的方法和步骤。
摘要由CSDN通过智能技术生成

codeforces 1557 C Moamen and XOR

题目链接

题目标签

递推、分类讨论

题目大意

有一个由 n n n个大小不超过 2 k 2^k 2k的非负整数组成的数组 a a a ,问有多少组 a a a满足条件 a 1 & a 2 & a 3 … … & a n ≥ a 1 ⊕ a 2 ⊕ a 3 … … ⊕ a n {a_1}\&{a_2}\&{a_3}……\&{a_n}\geq{a_1}⊕{a_2}⊕{a_3}……⊕{a_n} a1&a2&a3&ana1a2a3an

题目分析

这道题肯定先是将其转化为二进制的 0 0 0 1 1 1,这样结果最多会有 k k k

我们现在考虑这 n n n个数进行与运算和异或运算之后的结果

不难分析得出,只要有偶数个 1 1 1进行异或运算,最后结果就是 0 0 0,这样无论与运算的结果是什么,都满足题目条件

这样我们对 n n n的奇偶性进行分类讨论

首先考虑 n n n为奇数的情况

如果 n n n个数中有偶数个 1 1 1,则必定会有 0 0 0存在,这样n个数与运算结果必为 0 0 0,而异或结果必为 0 0 0

如果 n n n个数中有奇数个 1 1 1,则需要考虑是否有 0 0 0存在

如果没有 0 0 0存在,即 n n n个数全为 1 1 1,则与运算结果为 1 1 1,异或结果也为 1 1 1

如果有 0 0 0存在,即 n n n个数不全为 1 1 1,则与运算结果为 0 0 0,异或结果为 1 1 1

我们发现,当 n n n为奇数的时候,不存在 a 1 & a 2 & a 3 … … & a n > a 1 ⊕ a 2 ⊕ a 3 … … ⊕ a n {a_1}\&{a_2}\&{a_3}……\&{a_n}>{a_1}⊕{a_2}⊕{a_3}……⊕{a_n} a1&a2&a3&an>a1a2a3an的情况

所以我们需要这 k k k位均满足与运算结果等于异或运算结果

总共有 n n n个数,存在 2 n 2^n 2n种可能性,其中 1 1 1的个数为奇数和偶数的概率相同,故每一位有偶数个 1 1 1的情况有 2 n − 1 2^{n-1} 2n1种,再加上全为 1 1 1这一种情况,每一位有 2 n − 1 + 1 2^{n-1}+1 2n1+1种可能性, k k k位总共就有 ( 2 n − 1 + 1 ) k (2^{n-1}+1)^k (2n1+1)k种可能性

再考虑 n n n为偶数的情况

如果 n n n个数中有奇数个 1 1 1,则必定会有 0 0 0存在,这样n个数与运算结果必为 0 0 0,而异或结果为 1 1 1,不满足条件

如果 n n n个数中有偶数个 1 1 1,则需要考虑是否有 0 0 0存在

如果没有 0 0 0存在,即 n n n个数全为 1 1 1,则与运算结果为 1 1 1,异或结果为 0 0 0

如果有 0 0 0存在,即 n n n个数不全为 1 1 1,则与运算结果为 0 0 0,异或结果为 0 0 0

我们定义一个函数 f ( x ) f(x) f(x)为二进制有 x x x位的满足条件的组数

我们从第 k k k位开始考虑

如果第 k k k位的 n n n个数全为 1 1 1,那么后面位置的数无论是多少,都满足题目条件,这样后面的数有 k − 1 k-1 k1位,共 n n n个数,那么总共有 ( 2 k − 1 ) n (2^{k-1})^n (2k1)n种可能性

如果第 k k k位的 n n n个数不全为 1 1 1但是有偶数个 1 1 1,那我们需要算出满足此情况的种类数总共有 ( 2 n − 1 − 1 ) (2^{n-1}-1) (2n11),再乘上第 k − 1 k-1 k1位种类数,即 f ( k − 1 ) f(k-1) f(k1),最终递归到第 1 1 1位,第 1 1 1位需要满足偶数个 1 1 1即可

综上,当 n n n为偶数的时候 f ( k ) = ( 2 n − 1 − 1 ) f ( k − 1 ) + ( 2 k − 1 ) n f(k)=(2^{n-1}-1)f(k-1)+(2^{k-1})^n f(k)=(2n11)f(k1)+(2k1)n结果递归即可

记得要快速幂取模

AC代码

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
ll T,n,k;
typedef long long ll;
ll mod = 1e9+7;
ll ans;

ll fast_pow(ll a,ll b) {
    ll ans = 1;
    ll base = a%mod;
    while(b) {
        if(b&1)
            ans = (ans*base)%mod;
        b>>=1;
        base = (base*base)%mod;
    }
    return ans ;
}

int main() {
    cin>>T;
    while(T--) {
        cin>>n>>k;
        if(k==0) {
            cout<<1<<endl;
            continue;
        }
        if(n&1) {
            ans = fast_pow(fast_pow(2,n-1)+1,k);
            cout<<ans<<endl;
        }
        else {
            ans = fast_pow(2,n-1);
            for(ll i=2;i<=k;i++)
                ans = (((fast_pow(2,n-1)-1)*ans)%mod+fast_pow(2,(i-1)*n))%mod;
            cout<<ans<<endl;
        }
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值