hdu 6395 Sequence 分块矩阵快速幂

 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6395

我真的服了,一直不知道T在哪里

最后改着改着变成wa了,发现是mod数写错了,改了就过了

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define mod  1000000007
#define For(i,m,n) for(int i=m;i<=n;i++)
#define Dor(i,m,n) for(int i=m;i>=n;i--)
#define LL long long
#define lan(a,b) memset(a,b,sizeof(a))
using namespace std;

struct node
{
    int n;
    LL rect[5][5];
//    struct node operator* (const node b)
//    {
//        node tem;
//        tem.n=n;
//        for(int i=1;i<=n;i++)
//            for(int j=1;j<=n;j++)
//            {
//                tem.rect[i][j]=0;
//                for(int k=1;k<=n;k++)
//                        tem.rect[i][j]=(tem.rect[i][j]+rect[i][k]*b.rect[k][j])%mod;
//            }
//        return tem;
//    };
};


node mul(node x,node y)
{
    node s;
    lan(s.rect,0);
    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
        for(int k=1;k<=3;k++)
        s.rect[i][j]=(s.rect[i][j]+x.rect[i][k]*y.rect[k][j]%mod)%mod;

    return s;
}


node tem;
LL A,B,C,D,p,n;

node pow(LL b)
{
	node res;
	lan(res.rect,0);
	res.rect[3][3]=res.rect[1][1]=res.rect[2][2]=1;
    while(b)
    {
        if(b&1) res=mul(res,tem);
//        printf("b=%lld\n",b);
       tem=mul(tem,tem);
        b>>=1;
    }
//        printf("ok\n");
    return res;
}



LL solve(LL i)
{
	LL l=i,r=n;
	LL P=p/i;
	while(l<r)
	{
		int mid=r-(r-l)/2;
		if(P==p/mid)l=mid;
		else if(P>p/mid)r=mid-1;
		else l=mid+1;
	}
	return l;
}

void init(int x)
{
        tem.rect[1][1]=D,tem.rect[1][2]=C,tem.rect[1][3]=x;
        tem.rect[2][1]=1,tem.rect[2][2]=0,tem.rect[2][3]=0;
        tem.rect[3][1]=0,tem.rect[3][2]=0,tem.rect[3][3]=1;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
      scanf("%lld%lld%lld%lld%lld%lld",&A,&B,&C,&D,&p,&n);
      lan(tem.rect,0);
        if(n<=2)
        {
            if(n==1)
                printf("%lld\n",A);
            else if(n==2)
                printf("%lld\n",B);
            continue;
        }
    LL l=3,r;
    LL f1=B,f2=A;
    for(l=3;l<=n;)
    {
        r=solve(l);
//        r=p/l==0?n:min(n,p/(p/l));
//        printf("l=%lld r=%lld\n",l,r);
        LL len=r-l+1;
        init(p/l);
        tem=pow(len);

        LL ff1=(tem.rect[1][1]*f1%mod+tem.rect[1][2]*f2%mod+tem.rect[1][3])%mod;
        LL ff2=(tem.rect[2][1]*f1%mod+tem.rect[2][2]*f2%mod+tem.rect[2][3])%mod;

        f1=ff1;
        f2=ff2;

        l=r+1;
    }
    printf("%lld\n",f1);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值