hdu6395 Sequence(矩阵快速幂+分段)

Let us define a sequence as below

⎧⎩⎨⎪⎪⎪⎪⎪⎪F1F2Fn===ABC⋅Fn−2+D⋅Fn−1+⌊Pn⌋{F1=AF2=BFn=C⋅Fn−2+D⋅Fn−1+⌊Pn⌋



  Your job is simple, for each task, you should output FnFn module 109+7109+7.

Input

The first line has only one integer TT, indicates the number of tasks.

Then, for the next TT lines, each line consists of 66 integers, AA , BB, CC, DD, PP, nn.

1≤T≤200≤A,B,C,D≤1091≤P,n≤1091≤T≤200≤A,B,C,D≤1091≤P,n≤109

Sample Input

2
3 3 2 1 3 5
3 2 2 2 1 4

Sample Output

36
24

题不难,就是情况不太好处理,花费了不少时间代码:

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<math.h>
#include<bitset>
using namespace std;
#define ll long long
#define mod 1000000007
void mul(ll f[3],ll a[3][3])//模板
{
    ll c[3];
    memset(c,0,sizeof(c));
    for(ll j=0; j<3; j++)
        for(ll k=0; k<3; k++)
            c[j]=(c[j]+(f[k]*a[k][j]+mod)%mod+mod)%mod;
    memcpy(f,c,sizeof(c));
}
void mulself(ll a[3][3])//模板
{
    ll c[3][3];
    memset(c,0,sizeof(c));
    for(ll i=0; i<3; i++)
        for(ll j=0; j<3; j++)
            for(ll k=0; k<3; k++)
                c[i][j]=(c[i][j]+(a[i][k]*a[k][j]+mod)%mod+mod)%mod;
    memcpy(a,c,sizeof(c));
}
void assignment(ll a[3][3],ll b[3][3])//分段每次都要给a重新赋值
{
    for(ll i=0; i<3; i++)
        for(ll j=0; j<3; j++)
            a[i][j]=b[i][j];
}
int main()
{
    ll t,A,B,C,D,p,n,m;
    scanf("%lld",&t);
    while(t--)
    {
        scanf("%lld%lld%lld%lld%lld%lld",&A,&B,&C,&D,&p,&n);
        ll f[3]= {A,B},a[3][3],b[3][3]= {{0,C,0},{1,D,0},{0,1,1}};
        if(n==1||n==2)//此情况不处理
            ;
        else if(p>n)//p>n时的分段
        {
            for(ll l = 3, r; l <= n; l = r + 1)
            {
                r = min(n,p / (p / l)),m=(r-l+1),f[2]=p/l;
                assignment(a,b);
                for(; m; m>>=1)
                {
                    if(m&1)
                        mul (f,a);
                    mulself(a);
                }
            }
        }
        else//p<n时的分段
        {
            for(ll l = 3, r; l <= p; l = r + 1)
            {
                r = p / (p / l),m=(r-l+1),f[2]=p/l;
                assignment(a,b);
                for(; m; m>>=1)
                {
                    if(m&1)
                        mul (f,a);
                    mulself(a);
                }
            }
            assignment(a,b);
            m=n-max(p,2ll),f[2]=0;
            for(; m; m>>=1)
            {
                if(m&1)
                    mul (f,a);
                mulself(a);
            }
        }
        printf("%lld\n",(f[1]+mod)%mod);//要用f[1],用f[0]时,f[1]的值就会变
    }
    return 0;
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值