GukiZ and Binary Operations(矩阵+二进制)

D. GukiZ and Binary Operations

time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

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 过的。

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

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define LL  long long
using namespace std;//unsigned
struct matrix
{
    LL mat[2][2];
};
LL mod;

matrix multiply(matrix a,matrix b)
{
    matrix c;
    memset(c.mat,0,sizeof(c.mat));
    for(int i=0;i<2;i++)
    {
        for(int j=0;j<2;j++)
        {
            if(a.mat[i][j]==0)continue;
            for(int k=0;k<2;k++)
            {
                if(b.mat[j][k]==0)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]<0) c.mat[i][k]+=mod;
            }
        }
    }
    return c;
}

matrix quicklymod(matrix a,LL n)
{
    matrix res;
    memset(res.mat,0,sizeof(res.mat));
    for(int i=0;i<2;i++) res.mat[i][i]=1;
    while(n)
    {
        if(n&1)
            res=multiply(a,res);
        a=multiply(a,a);
        n>>=1;
    }
    return res;
}

LL ppow(LL a,LL b)
{
    LL c=1;
    while(b)
    {
        if(b&1) c=c*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return c;
}

int main()
{
    LL n,k,l,m;
    scanf("%I64d%I64d%I64d%I64d",&n,&k,&l,&mod);
    if(l!=64&&k>=(unsigned long long )(1ULL<<l)){printf("0\n");return 0;}
    matrix ans;
    ans.mat[0][0]=1;ans.mat[0][1]=1;
    ans.mat[1][0]=1;ans.mat[1][1]=0;
    ans=quicklymod(ans,n);
    //相邻没有连续两个1
    LL x=(ans.mat[0][0]+ans.mat[0][1])%mod;
    //至少有一个连续两个1
    LL y=((ppow(2,n)-x)%mod+mod)%mod;
 //  printf("x=%I64d\ty=%I64d\n",x,y);
    LL sum=1;
    for(LL i=0;i<l;i++)
    {
        if(k&(1LL<<i)) sum=(sum*y)%mod;
        else sum=sum*x%mod;
    }
    printf("%I64d\n",sum%mod);
    return 0;
}

时间: 2024-10-25 21:25:35

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

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

Problem E. GukiZ and GukiZiana Solution 一位一位考虑,就是求一个二进制序列有连续的1的种类数和没有连续的1的种类数. 没有连续的1的二进制序列的数目满足f[i]=f[i-1]+f[i-2],恰好是斐波那契数列. 数据范围在10^18,用矩阵加速计算,有连续的1的数目就用2^n-f[n+1] 最后枚举k的每一位,是1乘上2^n-f[n+1],是0乘上f[n+1] 注意以上需要满足 2^l>k.并且这里l的最大值为64,需要特判. #include <bit

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  mea

Codeforces 551 D. GukiZ and Binary Operations

\(>Codeforces \space 551 D. GukiZ and Binary Operations<\) 题目大意 :给出 \(n, \ k\) 求有多少个长度为 \(n\) 的序列 \(a\) 满足 \((a_1\ and \ a_2)or(a_2\ and \ a_3)or..or(a_{n-1}\ and \ a_n) = k\) 且 \(a_i \leq k \leq 2^l\) 并输出方案数在$\mod m $ 意义下的值 \(0≤?n ≤?10^{18},\ 0?≤?k

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

这个题刚开始是看错题了..一点思路都没有 到后来把题目看对了以后,有一点思路,但还是不会做..无奈只能看官方题解 官方题解是这样的: First convert number k into binary number system. If some bit of k is 0 than the result of or opertion applied for every adjacent pair of those bits in array a must be 0, that is no t

[Introduction to programming in Java 笔记] 1.3.7 Converting to binary 十进制到二进制的转换

public class Binary { public static void main(String[] args) { // Print binary representation of N. int N = Integer.parseInt(args[0]); int v = 1; while(v <= N/2) v = 2*v; // Now v is the largest power of 2 <= N. int n = N; // current excess while (v

Gym101158G Placing Medals on a Binary Tree(二进制模拟)

Gym101158G-Placing Medals on a Binary Tree 题意 一颗完全二叉树,给出n个点,xi的值表示深度为xi的点.问能否在当前状态下使得从根节点到该点的路径中不会遇到其他点. 思路 其实本题的意思就是 1/2,1/4,1/8等等等等,看剩下的点能不能减.然而由于k值并不小,所以long double也无法处理.其实完全二叉树给了启发,也就是如果当前深度的点占据了,相当于之后的子树都不能进行选择了.所以运算方式上类似二进制.相当于利用map对二进制进行模拟. 代码

待 题表

题表 达哥终极杂题表Bzoj2839 hdu6021 Codeforces 804DBzoj2248 hdu5575 Codeforces 786CBzoj2013 bzoj2676 Codeforces 803CBzoj2386 bzoj3782 Codeforces 813DBzoj2699 cogs1667 Codeforces 814DBzoj4798 bzoj2064 Codeforces 814EBzoj4639 bzoj3505 Codeforces 815ABzoj4417 bz

涉及到复制和二进制日志中的选项和变量-Replication and Binary Logging Options and Variables

在搭建复制中,有些参数需要我们留意,在这里罗列出来,供大家参考一下,以GTID为基础 --server-id server-id:这是一个全局的可动态调整的变量,取值范围为0-4294967295,也就是2的32次方减1,这个选项必须在master和slave中都分别进行设置,如果不设置保持默认,则在连接过程中会产生错误.从而复制失败,将这个参数配置在my.cnf配置文件中,然后重启生效 2. --server_uuid server_uuid:这是一个全局只读的变量,非动态变量,以一个字符串的

MySQL 二进制日志(Binary Log)

同大多数关系型数据库一样,日志文件是MySQL数据库的重要组成部分.MySQL有几种不同的日志文件,通常包括错误日志文件,二进制日志,通用日志,慢查询日志,等等.这些日志可以帮助我们定位mysqld内部发生的事件,数据库性能故障,记录数据的变更历史,用户恢复数据库等等.二进制日志,也叫binary log,是MySQL Server中最为重要的日志之一,本文主要描述二进制日志. 1.MySQL日志文件系统的组成   a.错误日志:记录启动.运行或停止mysqld时出现的问题.   b.通用日志: