hdu_2276_构造矩阵_快速幂乘

/*
非递归的二分用3^n模拟,比如下面代码的p,a分别出现的是:3 3^2,3^3 3^4,3^7 3^8,3^15 3^16 ....3^i-1 3^i(i=2^k)

a1=(a1+an)%2

a2=(a1+a2)%2

a3=(a1+a2)%2.............ai=(a(i-1)+ai)%2;

有这种关系,我们想到用矩阵去运算,先要构造一个矩阵!

| 1 0 0 0 ....1 |

| 1 1 0 0.....0 |    

| 0 1 1 0 ....0| 

     ......
*/

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;

struct mat
{
    int m[100][100];
};

int m;
int len;

mat product(mat a,mat b)
{
    mat c;
    int i,j,k;
    memset(c.m,0,sizeof(c.m));
    for(i=0;i<len;i++)
        for(j=0;j<len;j++)
        {
            for(k=0;k<len;k++)
                c.m[i][j]+=a.m[i][k]*b.m[k][j];
            c.m[i][j]%=2;
        }
        return c;
}

mat div(mat a,int x)        //如果用递归解决的话就爆内存,只能用非递归,而且还要注意用二分法,非递归的话可以用2^7模拟,
{
    mat p;        //p为单位矩阵
    int i,j;
    for(i=0;i<len;i++)
        for(j=0;j<len;j++)
            p.m[i][j]=(i==j);
    while(x)
    {
        if(x&1)
            p=product(p,a);
        x>>=1;
        a=product(a,a);
    }
    return p;
}

int main()
{
    char s[100],ans[100];
    mat a;
    int c[100],d[100];
    int i,j,k;
    while(scanf("%d",&m)!=EOF)
    {
        scanf("%s",s);
        len=strlen(s);
        memset(a.m,0,sizeof(a.m));
        a.m[0][len-1]=1;
        for(i=0;i<len;i++)
            for(j=0;j<len;j++)
                if(i==j||i-1==j)
                    a.m[i][j]=1;
                mat b;
                b=div(a,m);
                for(i=0;i<len;i++)
                    c[i]=s[i]-'0';
                memset(d,0,sizeof(d));
                for(i=0;i<len;i++)
                    for(j=0;j<len;j++)
                        d[i]=(d[i]+b.m[i][j]*c[j])%2;
                    for(i=0;i<len;i++)
                        ans[i]=d[i]+'0';
                    ans[len]='/0';
                    printf("%s/n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值