CodeForces 551 D.GukiZ and Binary Operations(dp+矩阵快速幂)

本文介绍了一种使用矩阵快速幂的方法来解决特定类型的计数问题。输入为四个整数n, k, l, m,在给定条件下计算满足特定条件的序列数量,并将结果对m取模。通过矩阵乘法和快速幂操作实现高效计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description
这里写图片描述
Input
四个整数n,k,l,m (2<=n<=1e18,0<=k<=1e18,0<=l<=64,1<=m<=1e9+7)
Output
输出满足条件的序列a个数,结果模m
Sample Input
2 1 2 10
Sample Output
3
Solution
这里写图片描述
Code

#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
struct Mat
{
    int mat[3][3];//矩阵 
    int row,col;//矩阵行列数 
};
Mat mod_mul(Mat a,Mat b,int p)//矩阵乘法 
{
    Mat ans;
    ans.row=a.row;
    ans.col=b.col;
    memset(ans.mat,0,sizeof(ans.mat));
    for(int i=0;i<ans.row;i++)      
        for(int k=0;k<a.col;k++)
            if(a.mat[i][k])
                for(int j=0;j<ans.col;j++)
                    ans.mat[i][j]=(ans.mat[i][j]+(ll)a.mat[i][k]*b.mat[k][j])%p;
    return ans;
}
Mat mod_pow(Mat a,ll k,int p)//矩阵快速幂 
{
    Mat ans;
    ans.row=a.row;
    ans.col=a.col;
    for(int i=0;i<a.row;i++)
        for(int j=0;j<a.col;j++)
            ans.mat[i][j]=(i==j);
    while(k)
    {
        if(k&1)ans=mod_mul(ans,a,p);
        a=mod_mul(a,a,p);
        k>>=1;
    }
    return ans;
}
int inc(int a,int b,int m)
{
    return a+b>=m?a+b-m:a+b;
}
int dec(int a,int b,int m)
{
    return a-b<0?a-b+m:a-b;
}
int Pow(int a,ll b,int p)
{
    int ans=1;
    while(b)
    {
        if(b&1)ans=(ll)ans*a%p;
        a=(ll)a*a%p;
        b>>=1;
    }
    return ans;
}
int l,m;
ll n,k;
Mat A;
int main()
{
    A.row=A.col=2;
    A.mat[0][0]=A.mat[0][1]=A.mat[1][0]=1,A.mat[1][1]=0;
    while(~scanf("%I64d%I64d%d%d",&n,&k,&l,&m))
    {
        int res=0,num0=0,num1=0;
        while(k)
        {
            res++;
            if(k&1)num1++;
            k/=2;
        }
        num0=l-num1;
        if(res>l)printf("0\n");
        else
        {
            Mat B=mod_pow(A,n,m);
            int ans1=(B.mat[0][0]+B.mat[0][1])%m;
            int ans2=dec(Pow(2,n,m),ans1,m);
            int ans=(ll)Pow(ans1,num0,m)*Pow(ans2,num1,m)%m;
            printf("%d\n",ans);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值