D. GukiZ and Binary Operations(矩阵+二进制)
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!
First and the only line of input contains four integers n, k, l, m (2 ≤ n ≤ 1018, 0 ≤ k ≤ 1018, 0 ≤ l ≤ 64, 1 ≤ m ≤ 109 + 7).
In the single line print the number of arrays satisfying the condition above modulo m.
2 1 2 10
3
2 1 1 3
1
3 3 2 10
9
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}.
,两两取与再取或的方式最后答案为k,问你有多少种方案数,答案取余m注意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(矩阵+二进制)的更多相关文章
- Codeforces 551D GukiZ and Binary Operations(矩阵快速幂)
Problem D. GukiZ and Binary Operations Solution 一位一位考虑,就是求一个二进制序列有连续的1的种类数和没有连续的1的种类数. 没有连续的1的二进制序列的 ...
- 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 ...
- Codeforces 551 D. GukiZ and Binary Operations
\(>Codeforces \space 551 D. GukiZ and Binary Operations<\) 题目大意 :给出 \(n, \ k\) 求有多少个长度为 \(n\) ...
- Codeforces Round #307 (Div. 2) D. GukiZ and Binary Operations (矩阵高速幂)
题目地址:http://codeforces.com/contest/551/problem/D 分析下公式能够知道,相当于每一位上放0或者1使得最后成为0或者1.假设最后是0的话,那么全部相邻位一定 ...
- GukiZ and Binary Operations CodeForces - 551D (组合计数)
大意: 给定$n,k,l,m$, 求有多少个长度为$n$, 元素全部严格小于$2^l$, 且满足 的序列. 刚开始想着暴力枚举当前or和上一个数二进制中$1$的分布, 但这样状态数是$O(64^3)$ ...
- Codeforces Round #307 (Div. 2) D. GukiZ and Binary Operations
得到k二进制后,对每一位可取得的方法进行相乘即可,k的二进制形式每一位又分为2种0,1,0时,a数组必定要为一长为n的01串,且串中不出现连续的11,1时与前述情况是相反的. 且0时其方法总数为f(n ...
- uestc 1709 Binary Operations 位运算的灵活运用
Binary Operations Time Limit: 2000 ms Memory Limit: 65535 kB Solved: 56 Tried: 674 Description B ...
- 位运算 UEST 84 Binary Operations
题目传送门 题意:所有连续的子序列的三种位运算计算后的值的和的期望分别是多少 分析:因为所有连续子序列的组数有n * (n + 1) / 2种,所以要将他们分类降低复杂度,以ai为结尾的分成一组,至于 ...
- SBX(Simulated binary crossover)模拟二进制交叉算子和DE(differential evolution)差分进化算子
一起来学演化计算-SBX(Simulated binary crossover)模拟二进制交叉算子和DE(differential evolution)差分进化算子 觉得有用的话,欢迎一起讨论相互学习 ...
随机推荐
- Flask上下文
Flask的核心机制!关于请求处理流程和上下文 学习一样东西不能只停留在表面,我们要探索其中的细节,学习作者的编程思想,这样才能更进一步. 关于WSGI WSGI(全称Web Server Gatew ...
- Android语音识别
语音识别 - 科大讯飞 开放平台 http://open.voicecloud.cn/ 需要拷贝lib.assets.并在清单文件中写一些权限 public class MainActivity ex ...
- java中编写增删改查
按照图书数据库来说 //查询 :查询的返回值有两种类型,如果返回的数据你不确定是一条还是多条就返回一个List集合.如果你确定数据返回的是一条,可以把返回值换成Book实体类型.public List ...
- spring boot整合 springmvc+mybatis
需要以下依赖 <dependencies> <dependency> <groupId>org.springframework.boot</groupId&g ...
- pycharm安装plugins
1 . 启动 PyCharm 软件 2 . 打开 设置(Setting) 窗口.(操作:File -> Setting 或者 按快捷键 Ctrl + Alt + S) 3 . 在搜索框里面搜索: ...
- Python 中的object takes no parameters错误
Python是一门面向对象的语言,中我们首先创建一个类: class Student(object): def _init_(self,name,score): self.name = name se ...
- Java中的enum枚举类
首先说说为什么要写这个enum枚举类吧,是群里有个新手问:怎样把enum类中的值遍历得到,其实自己用的也很少.自己也是确实不知道,于是我去网上搜了不少,总结了些,希望对大家有帮助:首先我说说怎样遍历枚 ...
- odoo开发笔记--form视图自定义
form视图自定义的两种场景: 1. 自己重写form视图样式文件 2. form视图,嵌入第三方的系统.
- c++中的左值与右值
左值(lvalue)和右值(rvalue)是 c/c++ 中一个比较晦涩基础的概念,不少写了很久c/c++的人甚至没有听过这个名字,但这个概念到了 c++11 后却变得十分重要,它们是理解 move/ ...
- mktemp 命令
Linux mktemp命令用于建立暂存文件. mktemp建立的一个暂存文件,供shell script使用. mktemp命令专门用来创建临时文件,并且其创建的临时文件是唯一的.shell会根据m ...