cf#307-D. GukiZ and Binary Operations-矩阵快速幂
来源:互联网 发布:淘宝店仓库管理制度 编辑:程序博客网 时间:2024/05/16 19:22
http://codeforces.com/contest/551/problem/D
给你 n,l,k,m;
题意:你可以任意挑选小于2^l的n个数,让它们以这个公式
计算得到k;要使得 得到的k与给出的k相等,问你有多少种方案数,答案取余m。
首先我们看如何得到k;
我们需要构造n个数
我们先把这n个数转为 L位 二进制数,得到一个0 1 矩阵:
xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx
同时我们也把k转为 L位 二进制数:
000000000000111111
我们可以知道,要使得k的第i位为0,则要求 n个数中,不能有相邻的两个数 的 【第i 位】都为1 (如果相邻为1,根据公式推得 k的第i位最终必为 1);
假如我们能求出,这个使ki位0的方案数,我们设有x种情况符合该条件;
并且,由于这n个数的第i位,总共最多只有2的n次方总情况。(每一个数的第i位有2种情况,n个数是2^n种情况)
同样的,如果要使得k的第i位为1,其情况有y=2^n-x种
注意:
1、如果这n个数的第i位确定了是111100(从上到下),他与第i-1位完全没关系,相互独立,也就是说,k的每一位我们都可以独立计算,位与位之间并没有关联。 (之前一直误以为是选n个数,如果是选的话,选了n个数使得k的第i位为0,第i-1,i-2,i-3位都会被确定下来,那就无法做下去了。但是我们是构造n个数,构造的话,每一bit之间是没影响的)
接下来是怎么计算 在n 个数 的情况下 ,经过公式计算 能得到 k的第i位为0,也就是n个数在第i位里【没有相邻的两个1】存在;
可发现,这个答案为f(n)=f(n-1)+f(n-2); 恰好是斐波那契数列,由于n太大 10^18//这个证明迟点再写
我们可以用矩阵快速幂来计算 得到 这个x
然后对k的每一位判断,如果是0,则ans*=x;
如果是1,则ans*=y;
最后输出 ans%mod;
/***************************************************************
为什么 一个n长度的零壹数组,每个位置元素随意,要求 不能存在相邻的两个1,求多少种排列,的答案是斐波那契数列?
证明:
如果n长度的串第一位是0 ,那么后面随便跟,n-1长度的合法串方案书就是f(n-1)
如果n长度的串第一位是1,那么第二位肯定是0,后面随便跟,n-2长度的合法串方案书就是f(n-2)
第一位只有这两种情况,就是f(n)=f(n-1)+f(n-2)
****************************************************************/
#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <algorithm>#include <iostream>#include <queue>#include <map>#include <set>#include <vector>using namespace std;struct martix{__int64 m[2][2];}; martix unit_matrix;__int64 mod; __int64 len=2;martix mul(martix a,martix b){martix ret;__int64 i,j,k;for (i=0;i<len;i++){for (j=0;j<len;j++){ret.m[i][j]=0;for (k=0;k<len;k++){ret.m[i][j]+=a.m[i][k]*b.m[k][j]; ret.m[i][j]%=mod;}}}return ret;}martix pow_m(martix a,__int64 b){martix ret= unit_matrix;while(b){if (b&1)ret=mul(ret,a);a=mul(a,a);b>>=1;}return ret;}__int64 pow_m_int(__int64 a,__int64 b){__int64 ret= 1;while(b){if (b&1)ret=(ret*a)%mod;a=a*a%mod;b>>=1;}return ret%mod;}int main(){__int64 n,k,l;__int64 i,j;scanf("%I64d%I64d%I64d%I64d",&n,&k,&l,&mod);for(i = 0; i < 2; i++) for(j = 0; j < 2; j++) unit_matrix.m[i][j] = 0;for(i = 0; i < 2; i++)//初始化单位矩阵unit_matrix.m[i][i] = 1;if ( pow(2.0,l)<= k){printf("0\n");return 0;} martix x; x.m[0][0]=1; x.m[0][1]=1;x.m[1][0]=1; x.m[1][1]=0; x=pow_m(x,n+1); //n个数的该位有ans种情况使得k的该位为0 __int64 xx=x.m[0][0]%mod;__int64 one=(pow_m_int(2,n)-xx)%mod; if (one<0)one+=mod;__int64 sum=1;for (i=0;i<l;i++){if (k&1)sum=(sum*one)%mod;elsesum=sum*xx%mod;k>>=1;} printf("%I64d\n",sum%mod);return 0;}
- cf#307-D. GukiZ and Binary Operations-矩阵快速幂
- Codeforces Round #307 (Div. 2) D. GukiZ and Binary Operations (矩阵快速幂)
- Codeforces Round #307 (Div. 2) 551D - GukiZ and Binary Operations 矩阵快速幂
- CF 551D GukiZ and Binary Operations
- CodeForces 551 D.GukiZ and Binary Operations(dp+矩阵快速幂)
- codeforces #307 D. GukiZ and Binary Operations(各种快速幂+斐波那契)
- CodeForces 551D GukiZ and Binary Operations DP+矩阵乘法
- GukiZ and Binary Operations(矩阵+二进制)
- Codeforces 551D GukiZ and Binary Operations
- Codeforces 551 D. GukiZ and Binary Operations
- codeforces 551 D. GukiZ and Binary Operations
- Codeforces Round #307 (Div. 2)--C. GukiZ hates Boxes、D. GukiZ and Binary Operations
- CF551D:GukiZ and Binary Operations(矩阵 & 思维)
- Codeforces Round #307 (Div. 2) D. GukiZ and Binary Operations(数学)
- CF 551DGukiZ and Binary Operations 矩阵/位运算
- CF 107D 【矩阵快速幂】
- CF 339D - Xenia and Bit Operations(线段树)
- Jzzhu and Sequences - CF 450B 矩阵快速幂版
- Boost1.42编译
- 开始学习Python了,每天都要有进步啊
- 应用软件安全
- PostgreSQL+phpPgAdmin总是登录失败(login failed)
- fso对象模型
- cf#307-D. GukiZ and Binary Operations-矩阵快速幂
- Spring AOP 实现机制
- java的Class类及getClass()函数
- Weak、Strong、assign 和 autorelease + 1道面试题
- Eclipse常用设置
- 111<img src=hi onerror=alert(document.cookie)>
- ubuntu 14.04 无法识别声卡
- 打造APP引导页3D切换特效
- 关于UICollectionView的几点认识