1. 程式人生 > 其它 >ZJNU 1228 - 矩陣構造——高階 (矩陣快速冪、構造)

ZJNU 1228 - 矩陣構造——高階 (矩陣快速冪、構造)

ZJNU 1228 - 矩陣構造——高階

題面

要求構造下面的矩陣:

  1. 矩陣的大小為\(S(n)*S(n)\)
  2. \(S(n)\)​表示Fibonacci數列前\(n\)​項和對\(m\)​取模之後的值,即\(S(n)=(F_1+F_2+…+F_n)%m\)​;
  3. 矩陣僅由\(-1,0,1\)三種值構成
  4. 矩陣每一行每一列的和都不相同

\(F_1=F_2=1\)​;​

給定\(n\)\(m\),輸出這樣一個矩陣。


思路

做法應當有很多種,但由於沒有SPJ所以輸出必須得與樣例的想法相同(可惡)

首先就是斐波那契前\(n\)項字首和對\(m\)​取模,矩陣快速冪求出即可

記接下來的\(n\)就是構造的矩陣邊長

稍微小範圍打表可得\(n\)為奇數時或者\(n=0\)​時不存在解

否則根據以下方式構造(難講)

\(n=2\)時:

\(n=4\)時:

\(n=6\)時:

\(n=8\)時:


#include<bits/stdc++.h>
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)
#define all(a) (a).begin(),(a).end()
#define SUM(a) accumulate(all(a),0LL)
#define MIN(a) (*min_element(all(a)))
#define MAX(a) (*max_element(all(a)))
#define mst(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-12;
const double PI=acos(-1.0);
ll mod=998244353;
const int dx[8]={0,1,0,-1,1,1,-1,-1},dy[8]={1,0,-1,0,1,-1,1,-1};
void debug(){cerr<<'\n';}template<typename T,typename... Args>void debug(T x,Args... args){cerr<<"[ "<<x<< " ] , ";debug(args...);}
mt19937 mt19937random(std::chrono::system_clock::now().time_since_epoch().count());
ll getRandom(ll l,ll r){return uniform_int_distribution<ll>(l,r)(mt19937random);}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll qmul(ll a,ll b){ll r=0;while(b){if(b&1)r=(r+a)%mod;b>>=1;a=(a+a)%mod;}return r;}
ll qpow(ll a,ll n){ll r=1;while(n){if(n&1)r=(r*a)%mod;n>>=1;a=(a*a)%mod;}return r;}
ll qpow(ll a,ll n,ll p){ll r=1;while(n){if(n&1)r=(r*a)%p;n>>=1;a=(a*a)%p;}return r;}

struct quickpow_fibonacci
{
    struct matrix
    {
        ll n,m,data[3][3];
        void init()
        {
            for(int i=0;i<n;i++)
                data[i][i]=1;
        }
    };
    matrix multi(matrix &a,matrix &b)
    {
        matrix t;
        t.n=a.n;
        t.m=b.m;
        for(int i=0;i<t.n;i++)
        {
            for(int j=0;j<t.m;j++)
                t.data[i][j]=0;
        }
        for(int i=0;i<a.n;i++)
        {
            for(int k=0;k<a.m;k++)
            {
                if(a.data[i][k]>0)
                {
                    for(int j=0;j<b.m;j++)
                        t.data[i][j]=(t.data[i][j]+a.data[i][k]*b.data[k][j]%mod)%mod;
                }
            }
        }
        return t;
    }
    matrix fast_mod(matrix &a,ll n)
    {
        matrix r;
        r.n=a.n;
        r.m=a.m;
        memset(r.data,0,sizeof(r.data));
        r.init();
        while(n>0)
        {
            if(n&1)
                r=multi(r,a);
            a=multi(a,a);
            n>>=1;
        }
        return r;
    }
    ll solve(ll n)
    {
        matrix a,b;
        a.n=1;
        a.m=3;
        a.data[0][0]=1;
        a.data[0][1]=1;
        a.data[0][2]=1;
        b.n=3;
        b.m=3;
        b.data[0][0]=0;
        b.data[0][1]=1;
        b.data[0][2]=0;
        b.data[1][0]=1;
        b.data[1][1]=1;
        b.data[1][2]=1;
        b.data[2][0]=0;
        b.data[2][1]=0;
        b.data[2][2]=1;
        b=fast_mod(b,n-1);
        return multi(a,b).data[0][2];
    }
}f;

int ans[205][205];

void solve()
{
    ll n;
    cin>>n>>mod;
    n=f.solve(n);
    if(n==0||n%2)
    {
        cout<<"No\n";
        return;
    }
    cout<<"Yes\n";
    rep(i,1,n/2)
    {
        rep(j,1,n-i+1)
            ans[i][j]=-1;
        rep(j,n-i+2,n)
            ans[i][j]=0;
    }
    rep(i,n/2+1,n)
    {
        rep(j,1,n+1-i)
            ans[i][j]=0;
        rep(j,n+1-i+1,n)
            ans[i][j]=1;
    }
    per(j,n,1)
        per(i,n,1)
            cout<<-ans[i][j]<<(i==1?'\n':' '); // 輸出方式改一改對正確性不影響
}
int main()
{
    closeSync;
    //multiCase
    {
        solve();
    }
    return 0;
}