D. GukiZ and Binary Operations

 

We all know that GukiZ often plays with arrays.

Now he is thinking about this problem: how many arrays a, of length n, with non-negative elements strictly less then 2l meet the following condition: ? Here operation  means bitwise AND (in Pascal it is equivalent to and, in C/C++/Java/Python it is equivalent to &), operation  means bitwise OR (in Pascal it is equivalent to , inC/C++/Java/Python it is equivalent to |).

Because the answer can be quite large, calculate it modulo m. This time GukiZ hasn't come up with solution, and needs you to help him!

Input

First and the only line of input contains four integers nklm (2 ≤ n ≤ 1018, 0 ≤ k ≤ 1018, 0 ≤ l ≤ 64, 1 ≤ m ≤ 109 + 7).

Output

In the single line print the number of arrays satisfying the condition above modulo m.

Sample test(s)
input
2 1 2 10
output
3
input
2 1 1 3
output
1
input
3 3 2 10
output
9
Note

In the first sample, satisfying arrays are {1, 1}, {3, 1}, {1, 3}.

In the second sample, only satisfying array is {1, 1}.

In the third sample, satisfying arrays are{0, 3, 3}, {1, 3, 2}, {1, 3, 3}, {2, 3, 1}, {2, 3, 3}, {3, 3, 0}, {3, 3, 1}, {3, 3, 2}, {3, 3, 3}.

题意:你可以任意挑选小于2^l的n个数,让它们以这个公式,两两取与再取或的方式最后答案为k,问你有多少种方案数,答案取余m
思路:这题看了别人的题解之后终于明白了。首先,我们把k转换为二进制来看,若某一位为1,则必须存在n个数中至少有相邻的两个数那一位都为1,若某一位为0,组必须存在n个数它们不能有相邻的两个数那一位都为1.这样我们相当于求k每一位在n个数字中的方案数,答案是每一位的方案数相乘起来。

注意l=64的时候,要特别注意一下

我用了无符号的long long 各种错。。。最后还是long long 过的。

不知道是不是我编译器坏了。

转载请注明出处:寻找&星空の孩子

题目链接:http://codeforces.com/contest/551/problem/D

 #include<stdio.h>
#include<string.h>
#include<algorithm>
#define LL long long
using namespace std;//unsigned
struct matrix
{
LL mat[][];
};
LL mod; matrix multiply(matrix a,matrix b)
{
matrix c;
memset(c.mat,,sizeof(c.mat));
for(int i=;i<;i++)
{
for(int j=;j<;j++)
{
if(a.mat[i][j]==)continue;
for(int k=;k<;k++)
{
if(b.mat[j][k]==)continue;
c.mat[i][k]+=a.mat[i][j]*b.mat[j][k]%mod;
// c.mat[i][k]%=mod;
if(c.mat[i][k]>mod) c.mat[i][k]-=mod;
else if(c.mat[i][k]<) c.mat[i][k]+=mod;
}
}
}
return c;
} matrix quicklymod(matrix a,LL n)
{
matrix res;
memset(res.mat,,sizeof(res.mat));
for(int i=;i<;i++) res.mat[i][i]=;
while(n)
{
if(n&)
res=multiply(a,res);
a=multiply(a,a);
n>>=;
}
return res;
} LL ppow(LL a,LL b)
{
LL c=;
while(b)
{
if(b&) c=c*a%mod;
b>>=;
a=a*a%mod;
}
return c;
} int main()
{
LL n,k,l,m;
scanf("%I64d%I64d%I64d%I64d",&n,&k,&l,&mod);
if(l!=&&k>=(unsigned long long )(1ULL<<l)){printf("0\n");return ;}
matrix ans;
ans.mat[][]=;ans.mat[][]=;
ans.mat[][]=;ans.mat[][]=;
ans=quicklymod(ans,n);
//相邻没有连续两个1
LL x=(ans.mat[][]+ans.mat[][])%mod;
//至少有一个连续两个1
LL y=((ppow(,n)-x)%mod+mod)%mod;
// printf("x=%I64d\ty=%I64d\n",x,y);
LL sum=;
for(LL i=;i<l;i++)
{
if(k&(1LL<<i)) sum=(sum*y)%mod;
else sum=sum*x%mod;
}
printf("%I64d\n",sum%mod);
return ;
}

别人的 无符号过的。。。

 #include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
typedef unsigned long long LL;
LL N,K,L,MOD;
struct Matrix
{
LL mat[][];
Matrix(){memset(mat,,sizeof(mat));}
Matrix operator*(Matrix A)
{
Matrix res;
for(int i=;i<;i++)
for(int j=;j<;j++)
for(int k=;k<;k++)
res.mat[i][j]=(res.mat[i][j]+mat[i][k]*A.mat[j][k]%MOD)%MOD;
return res;
}
};
LL pow_mul(LL x,LL n)
{
LL res=;
while(n)
{
if(n&)res=(res*x)%MOD;
x=(x*x)%MOD;
n>>=;
}
return res;
}
Matrix matrix_pow_mul(Matrix A,LL n)
{
Matrix res;
for(int i=;i<;i++)res.mat[i][i]=;
while(n)
{
if(n&)res=res*A;
A=A*A;
n>>=;
}
return res;
}
int main()
{
while(cin>>N>>K>>L>>MOD)
{
if(L!=&&K>=(1ULL<<L)){printf("0\n");continue;}
Matrix A,B;
A.mat[][]=A.mat[][]=A.mat[][]=;
A=matrix_pow_mul(A,N-);
B.mat[][]=;
B.mat[][]=;
A=A*B;
LL ans=;
LL sum=pow_mul(,N);
for(LL i=;i<L;i++)
{
if(K&(1LL<<i))ans=(ans*((sum-A.mat[][]+MOD)%MOD))%MOD;
else ans=(ans*A.mat[][])%MOD;
}
cout<<ans%MOD<<endl;
}
return ;
}
我用dp[i][j]表示有i个数,j表示最后一个数为0还是为1时满足没有相邻为1的方案数,因为n>=,所以i只有大于2才有意义。首先dp[][]=,dp[][]= , dp[][]=dp[][]+dp[][],dp[][]=dp[][] ………… 通项公式就是dp[n][]=dp[n-][]+dp[n-][],dp[n][]=dp[n-][] ,意思是当你长度为n最后一个数字为0时,你可以在长度为n-1最后一个数字为0或为1后面补0,这样不存在相邻为1的方案,若最后一位要为1,就只能在n-1最后一位为0的时候补1,这样才不会有相邻的1。最后你要计算的是all[n]=dp[n][]+dp[n][],其中dp[n][]==all[n-],dp[n][]==dp[n-][]==all[n-],推出all[n]=all[n-]+all[n-],这就是斐波那契数列。但这初始值有些不同,all[n] = fib[n+] ,fib第0个元素跟第1个元素为1. 算出不相邻的方案之后,只要算出总的方案数2^n(每一位取0或取1)减去不相邻的方案,即为相邻的方案。你也可以用dp去推一下,我稍微提一下,我用c[n]表示长度为n时具有相邻1的方案数,c[]= , c[]=c[]*+dp[][]………… c[n]=c[n-]*+dp[n-][]=c[n-]*+all[n-]这里的dp是上面求的不存在相邻的1,由于c[n-]具有相邻的1所以下一位任意,dp[n-][]是长度为n-1最后一位为1,我们补1让它有相邻的1.
得出是斐波那契数列之后,我们可以用矩阵快速幂求解斐波那契数,也可以用矩阵快速幂求c
注意:这道题wa点挺多的,首先是unsigned long long在判断是否越界的时候用,还有快速幂的次数是long long,枚举l位时候,第63位已经暴了10^,所以需要特判。最后输出结果要%mod,不然它有mod为1且l=0的样例

D. GukiZ and Binary Operations(矩阵+二进制)的更多相关文章

  1. Codeforces 551D GukiZ and Binary Operations(矩阵快速幂)

    Problem D. GukiZ and Binary Operations Solution 一位一位考虑,就是求一个二进制序列有连续的1的种类数和没有连续的1的种类数. 没有连续的1的二进制序列的 ...

  2. Codeforces Round #307 (Div. 2) D. GukiZ and Binary Operations 矩阵快速幂优化dp

    D. GukiZ and Binary Operations time limit per test 1 second memory limit per test 256 megabytes inpu ...

  3. Codeforces 551 D. GukiZ and Binary Operations

    \(>Codeforces \space 551 D. GukiZ and Binary Operations<\) 题目大意 :给出 \(n, \ k\) 求有多少个长度为 \(n\) ...

  4. Codeforces Round #307 (Div. 2) D. GukiZ and Binary Operations (矩阵高速幂)

    题目地址:http://codeforces.com/contest/551/problem/D 分析下公式能够知道,相当于每一位上放0或者1使得最后成为0或者1.假设最后是0的话,那么全部相邻位一定 ...

  5. GukiZ and Binary Operations CodeForces - 551D (组合计数)

    大意: 给定$n,k,l,m$, 求有多少个长度为$n$, 元素全部严格小于$2^l$, 且满足 的序列. 刚开始想着暴力枚举当前or和上一个数二进制中$1$的分布, 但这样状态数是$O(64^3)$ ...

  6. Codeforces Round #307 (Div. 2) D. GukiZ and Binary Operations

    得到k二进制后,对每一位可取得的方法进行相乘即可,k的二进制形式每一位又分为2种0,1,0时,a数组必定要为一长为n的01串,且串中不出现连续的11,1时与前述情况是相反的. 且0时其方法总数为f(n ...

  7. uestc 1709 Binary Operations 位运算的灵活运用

    Binary Operations Time Limit: 2000 ms Memory Limit: 65535 kB Solved: 56 Tried: 674   Description   B ...

  8. 位运算 UEST 84 Binary Operations

    题目传送门 题意:所有连续的子序列的三种位运算计算后的值的和的期望分别是多少 分析:因为所有连续子序列的组数有n * (n + 1) / 2种,所以要将他们分类降低复杂度,以ai为结尾的分成一组,至于 ...

  9. SBX(Simulated binary crossover)模拟二进制交叉算子和DE(differential evolution)差分进化算子

    一起来学演化计算-SBX(Simulated binary crossover)模拟二进制交叉算子和DE(differential evolution)差分进化算子 觉得有用的话,欢迎一起讨论相互学习 ...

随机推荐

  1. QEMU KVM libvirt 手册(3) - Storage Media

    访问Hard Drive 使用-hda –hdb qemu-system-x86_64 -enable-kvm -name ubuntutest  -m 2048 -hda ubuntutest.im ...

  2. MySQL--BNL/ICP/MRR/BKA

    #======================================================##MySQL关联查询算法:BNL(Block Nested-Loop)ICP(Index ...

  3. JavaScript的文档对象模型DOM

    小伙伴们之前我们讲过很多JavaScript的很多知识点,可以点击回顾一下: <JavaScript大厦之JS运算符>: <JavaScript工作原理:内存管理 + 如何处理4个常 ...

  4. 如何阅读Java源码?

    阅读本文大概需要 3.6 分钟. 阅读Java源码的前提条件: 1.技术基础 在阅读源码之前,我们要有一定程度的技术基础的支持. 假如你从来都没有学过Java,也没有其它编程语言的基础,上来就啃< ...

  5. 解决mysql插入数据报错[Err] 1146 - Table 'performance_schema.session_status' doesn't exist

    解决办法:1.打开cmd 执行命令cd/ 进入C盘根目录2.dir 查看C盘根目录下文件夹  找到 Program Files文件夹3.cd Program Files 进入该文件夹下 再输入dir ...

  6. 服务器端PHP允许跨域

    解决跨域的关键是设置 Access-Control-Allow-Origin. 例如:客户端的域名是 api.itbsl.com,而请求的域名是www.itbsl.com 如果直接使用ajax访问,会 ...

  7. 修改openstack用户配额

    修改openstack用户配额 这是我在工作中遇到的一个很有趣的小问题,当时的场景是这样的: 公司的云产品要上线数据库服务(trove),因为每创建数据库实例都要占用一个虚拟机及相关资源的配额,尤其是 ...

  8. [Postman]代理(16)

    代理服务器充当内部网络和Internet之间的安全屏障,使Internet上的其他人无法访问内部网络上的信息. 什么是代理? 在基本网络中,客户端向服务器发出请求,服务器发回响应. 代理服务器是充当计 ...

  9. VS解决-无法打开文件“opencv_ts300d.lib”问题

    之前使用过opencv,但不想要时没有正确去卸载,终造成历史问题,每次新建工程编译时都会弹出错误,然后停止运行,解决方法较笨笨 成功打印

  10. Python并发目录

    Python并发目录 Python-socket网络编程 Python网络编程-IO阻塞与非阻塞及多路复用 Python进程-理论 Python进程-实现 Python进程间通信 Python进程池 ...