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. AbstractRoutingDataSource 实现动态切换数据源

    扩展AbstractRoutingDataSource类 package com.datasource.test.util.database; import org.springframework.j ...

  2. Hadoop 单表关联

    前面的实例都是在数据上进行一些简单的处理,为进一步的操作打基础.单表关联这个实例要求从给出的数据中寻找到所关心的数据,它是对原始数据所包含信息的挖掘.下面进入这个实例. 1.实例描述 实例中给出chi ...

  3. 深入浅出Redis

    一.Redis的诞生 Redis创建者,出生于西西里岛的意大利人(antirez)发明的,个人网站,http://invece.org.早年是系统管理员,2004-2006 年做嵌入式方面的工作,之后 ...

  4. Ansible工具原理一

    ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet.cfengine.chef.func.fabric)的优点,实现了批量系统配置.批量程序部署.批量运行命 ...

  5. 本地语音识别开源软件pocketsphinx调试总结

    1问题一: fatal error: pocketsphinx.h: No such file or directory 解决方法: $ cd /usr/include $ sudo ln -s /m ...

  6. Event Loop浅谈

    event loop 即事件循环.最初了解到js的event loop机制是通过自己对js中异步.同步的疑惑.今天聊一聊自己的理解,希望和大家一起学习. 首先,让我们看一个经典的setTimeOut的 ...

  7. linux audit工具

    一个不错的博客,可以吸收营养,等读完后再决定写什么? https://www.cnblogs.com/bldly1989/p/7204358.html changelog -------------- ...

  8. 记录js new Date日期处理的一个坑

    记录js日期处理的一个坑   当前时区为北美东部时区时, new Date('2019-4-1') new Date('2019-04-01') 结果是相关一个月的. 如下图   new Date(' ...

  9. Github page搭建博客使用自定义插件的方法

    Github page的后台程序是由Jekyll搭建,但由于Github的保护措施,非认证的plugin一般不会被Github page支持,但可以使用一些小技巧来绕过屏蔽. 以个人page为例,个人 ...

  10. Android布局:宽度适应的横向跟随,防止挤掉重要视图

    不知道这样的布局该怎么描述,标题也是乱取的..直接上图吧 最近遇到了这样要求的布局: 1.上图中的“标题”长度不定,“状态”标签可能有多个并紧跟在标题右边,“属性”一直居右显示: 2.当“标题”过长, ...