codeforces #307 D. GukiZ and Binary Operations(各种快速幂+斐波那契)
2015-06-21 13:48
417 查看
题目链接:
罪恶的链接
题目大意:
有一个数组,(a1&&a2)|| ....... (an-1&&an)=k,ai<=2^l,求取这样的数组的数量%m
题目分析:
作为一个弱渣,这道题调了一上午才过,简直了。。。。
其实思路很简单,首先将k化为二进制数,那么如果k的某一个二进制位是0,那么也就是这个数组的相邻数位不可能全是1
因此我们得到如下的递推式:dp[i] = dp[i-1]+dp[i-2],当第i位放0时,那么有dp[i-1]中情况,如果第i位放1,那么第i-1位必须放0,所以有dp[i-2]种情况,正好可以看出是斐波那契数列,那么我们可以通过矩阵快速幂快速求取
然后看为1的情况,dp[i] = 2^n-1 + dp[i-1] ,表示当前两个数位都是1,那么其他的随便放,也就是2^n-1,如果当前两个数位不全是1,那么前面必有一个是1,所以是dp[i-1]种,但是这么做的话,递推起来又过于麻烦,可以突然想到只有1,0两种情况,一共的情况数是2^n,那么减掉0的情况不就是1的情况了吗!!!!被自己蠢哭了。。。
罪恶的链接
题目大意:
有一个数组,(a1&&a2)|| ....... (an-1&&an)=k,ai<=2^l,求取这样的数组的数量%m
题目分析:
作为一个弱渣,这道题调了一上午才过,简直了。。。。
其实思路很简单,首先将k化为二进制数,那么如果k的某一个二进制位是0,那么也就是这个数组的相邻数位不可能全是1
因此我们得到如下的递推式:dp[i] = dp[i-1]+dp[i-2],当第i位放0时,那么有dp[i-1]中情况,如果第i位放1,那么第i-1位必须放0,所以有dp[i-2]种情况,正好可以看出是斐波那契数列,那么我们可以通过矩阵快速幂快速求取
然后看为1的情况,dp[i] = 2^n-1 + dp[i-1] ,表示当前两个数位都是1,那么其他的随便放,也就是2^n-1,如果当前两个数位不全是1,那么前面必有一个是1,所以是dp[i-1]种,但是这么做的话,递推起来又过于麻烦,可以突然想到只有1,0两种情况,一共的情况数是2^n,那么减掉0的情况不就是1的情况了吗!!!!被自己蠢哭了。。。
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <vector> #define MAX 2 using namespace std; typedef long long LL; LL m,n,l,k; struct Matrix { LL a[MAX][MAX]; }; void reset ( Matrix& m ) { memset ( m.a , 0 , sizeof ( m.a ) ); } void set ( Matrix& m ) { memset ( m.a , 0 , sizeof ( m.a ) ); for ( int i = 0 ; i < 2 ; i++ ) m.a[i][i] = 1; } Matrix multi ( Matrix m1 , Matrix m2 ) { Matrix ret; reset ( ret ); for ( int i = 0 ; i < 2 ; i++ ) for ( int j = 0 ; j < 2 ; j++ ) if ( m1.a[i][j] ) for ( int k = 0 ; k < 2 ; k++ ) ret.a[i][k] = (ret.a[i][k] + m1.a[i][j] * m2.a[j][k]%m)%m; return ret; } Matrix quickMulti ( Matrix m1 , LL n ) { Matrix ret; set ( ret ); while ( n ) { if ( n&1 ) ret = multi ( ret , m1 ); m1 = multi ( m1 , m1 ); n >>= 1; } return ret; } LL pow ( LL x , LL n ) { LL ret = 1; while ( n ) { if ( n&1 ) ret = ret*x%m; x = x*x%m; n >>= 1; } return ret; } Matrix a,b; LL ans; void init ( ) { reset ( b ); b.a[0][0] = b.a[0][1] = b.a[1][0] = 1; ans = 1; } int main ( ) { while ( cin >> n >> k >> l >> m ) { init(); b = quickMulti ( b , n+1 ); LL k1 = b.a[0][0]; LL k2 = ((pow (2,n)-k1)%m+m)%m; int cnt = 0; if ( m == 1 ) { puts ("0"); continue; } if ( l < 63 && (1LL<<l) <= k ) { puts ( "0" ); continue; } if ( l == 0 ) { if ( k == 0 ) puts("1"); else puts("0"); continue; } while ( k ) { if ( k&1 ) ans = ans*k2%m; else ans = ans*k1%m; k >>= 1; cnt++; } while ( cnt++ < l ) ans = ans*k1%m; ans = (ans%m+m)%m; cout << ans << endl; } }
相关文章推荐
- 调用ShellExecute需要头文件
- 深入浅出 nginx lua 为什么高性能
- 在xbox配置hadoop伪分布中主要遇到的问题以及解决的办法
- tomcat通过conf-Catalina-localhost目录发布项目详解
- Bash变量扩展修改符
- PS1环境变量
- linux apache
- bottle框架学习(五)之文件的下载与上传
- apache模块开发之helloworld
- 关于linux依赖关系出错的解决
- 一个星期自动态的网站设计
- linux下安装unity web player的方法
- JavaWeb:Tomcat下配置数据源连接数据库
- 菜鸟教程工具(三)——Maven自己主动部署Tomcat
- Linux下samba服务器搭建(未完待续)
- Linux|XAMPP 搭建Discuz论坛二
- 如何在Git中撤销一切
- TopCoder SRM 660 Div2 Problem 1000 - Powerit (数论)
- Tomcat源码阅读(五)Service
- Linux学习(一)