首页 > 代码库 > 【HNOI2002】【矩阵快速幂】公交车路线

【HNOI2002】【矩阵快速幂】公交车路线

仍然是学弟出的题目的原题@lher 学弟将题目改成了多组数据,n在ll范围内,所以我就只讲提高版的做法。

链接:https://www.luogu.org/problem/show?pid=2233

题意分析:看题目:)

解题思路:显然对于n为奇数的情况不存在任意路线。接下来我们进行观察数据,显然这题是要递推的。接下来通过暴力打表加手算,我们推出了这个公式:

f[i]=4*f[i-1]-2*f[i-2],f[1]=2,f[2]=8,然后构造对应矩阵进行矩阵快速幂即可得到答案。时间效率O(8Tlog(n))。

附AC代码:

#include<stdio.h>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#define ll long long
#define mod 10007
using namespace std;
struct zxy{
    ll a[2][2];
}jichu,a,b;
ll n;
inline ll in(){
    ll x=0,f=1;
    char ch=getchar();
    while(ch<0||ch>9) {if(ch==-) f=-1; ch=getchar();}
    while(ch>=0&&ch<=9) x=x*10+ch-0,ch=getchar();
    return x*f;
}
inline zxy mult(zxy a,zxy b){
    zxy c;
    memset(c.a,0,sizeof(c.a));
    for (int i=0; i<=1; ++i)
        for (int j=0; j<=1; ++j)
            for (int k=0; k<=1; ++k)
                c.a[i][j]+=(a.a[i][k]*b.a[k][j]+2*mod)%mod,c.a[i][j]=(c.a[i][j]+2*mod)%mod;
    return c;
}
inline zxy ksm(zxy a,ll k){
    if (k==0) return jichu;
    if (k==1) return a;
    zxy tt=ksm(a,k>>1);
    if (k&1) return mult(a,mult(tt,tt));
    return mult(tt,tt);
}
int main(){
    int T=in();
    memset(jichu.a,0,sizeof(jichu.a));
    memset(b.a,0,sizeof(b.a));
    memset(a.a,0,sizeof(a.a));
    jichu.a[0][0]=jichu.a[1][1]=1;
    b.a[0][0]=2;b.a[1][0]=8;
    a.a[0][1]=1;a.a[1][0]=-2+mod,a.a[1][1]=4;
    while(T--){
        n=in();
        if (n&1) printf("0\n");
        else{
            n=n/2-2;
            if (n<2) printf("%lld\n",b.a[n][0]);
            else{ zxy ans=mult(ksm(a,n-1),b);printf("%lld\n",ans.a[1][0]);}
        }
    }
    return 0;
}

 

【HNOI2002】【矩阵快速幂】公交车路线