道路 - 矩阵乘法 - 倍增

题目大意:给定一张图GGG,求∑i=1kiTGi,T,∣G∣≤50,k≤109\sum_{i=1}^ki^TG^i,T,|G|\le50,k\le10^9i=1kiTGi,T,G50,k109
题解:
一些显然的做法是把那个幂次拆成斯特林数然后就是要求从路径上再选出若干条不同的边的方案数,这个就可以直接拿来倍增做到O(n^5lgk)了。
考虑直接对这个倍增:
ST(k)=∑i=1kiTGiST(a+b)=ST(a)+∑i=1b(i+a)TGi+a=ST(a)+Ga∑i=1b∑j=0T(Tj)ijaT−jGi=ST(a)+Ga∑j=0T(Tj)aT−j∑i=1bijGi=ST(a)+Ga∑j=0T(Tj)aT−jSj(b)S_T(k)=\sum_{i=1}^ki^TG^i\\ S_T(a+b)=S_T(a)+\sum_{i=1}^b(i+a)^TG^{i+a}\\ =S_T(a)+G^a\sum_{i=1}^b\sum_{j=0}^T\binom Tji^ja_{T-j}G^i\\ =S_T(a)+G^a\sum_{j=0}^T\binom Tja^{T-j}\sum_{i=1}^bi^jG^i\\ =S_T(a)+G^a\sum_{j=0}^T\binom Tja^{T-j}S_j(b)ST(k)=i=1kiTGiST(a+b)=ST(a)+i=1b(i+a)TGi+a=ST(a)+Gai=1bj=0T(jT)ijaTjGi=ST(a)+Gaj=0T(jT)aTji=1bijGi=ST(a)+Gaj=0T(jT)aTjSj(b)
因此维护(Gk,S0(k),S1(k),…,ST(k))\left(G^k,S_0(k),S_1(k),\dots,S_T(k)\right)(Gk,S0(k),S1(k),,ST(k))即可。
每次算一个ST(k)S_T(k)ST(k)需要TTT次加法和111次乘法,因此算每个ST(k)S_T(k)ST(k)复杂度是O(Tn2+n3)O\left(Tn^2+n^3\right)O(Tn2+n3),因此总复杂度O(T(Tn2+n3)lg⁡k)O\left(T\left(Tn^2+n^3\right)\lg k\right)O(T(Tn2+n3)lgk)

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define mod 1000000007
#define ull unsigned lint
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
inline int fast_pow(int x,int k,int ans=1) { for(;k;k>>=1,x=(lint)x*x%mod) (k&1)?ans=(lint)ans*x%mod:0;return ans; }
const int N=52;
namespace MAT{
    int n;
    struct mat{
        int v[N][N];
        inline int& operator()(int x,int y) { return v[x][y]; }
        inline int clear() { rep(i,1,n) memset(v[i],0,sizeof(int)*(n+1));return 0; }
        inline mat operator*(const mat &b)const
        {
            const mat &a=*this;static mat res;res.clear();
            rep(i,1,n) rep(j,1,n)
            {
                int v=0,k=1;ull w=0;
                #define P(k) (ull)a.v[i][k]*b.v[k][j]
                for(;k+15<=n;k+=16)
                    v=(v+P(k+0)+P(k+1)+P(k+2)+P(k+3)+P(k+4)+P(k+5)+P(k+6)+P(k+7)
                        +P(k+8)+P(k+9)+P(k+10)+P(k+11)+P(k+12)+P(k+13)+P(k+14)+P(k+15))%mod;
                for(;k<=n;k++) w+=P(k);res.v[i][j]=(v+w)%mod;
                #undef P
            }
            return res;
        }
        inline mat& operator*=(const mat &b) { return (*this)=(*this)*b,*this; }
        inline mat operator*(int x)const
        {
            static mat res;res=*this;
            rep(i,1,n) rep(j,1,n) res.v[i][j]=(lint)res.v[i][j]*x%mod;
            return res;
        }
        inline mat& operator*=(int x) { return (*this)=(*this)*x,*this; }
        inline mat operator+(const mat &b)const
        {
            static mat res;res=*this;
            rep(i,1,n) rep(j,1,n) { int &x=res.v[i][j];x+=b.v[i][j],(x>=mod?x-=mod:0); }
            return res;
        }
        inline mat& operator+=(const mat &b) { return (*this)=(*this)+b,*this; }
    }I;
    inline mat operator*(int x,const mat &b) { return b*x; }
    inline int _init(int _n) { n=_n;rep(i,1,n) I(i,i)=1;return 0; }
}
using MAT::I;using MAT::mat;mat g;
namespace BIGMAT{
    int T,C[N][N],mi[N];
    inline int _init(int _T)
    {
        T=_T;rep(i,0,T) C[i][0]=1;
        rep(i,1,T) rep(j,1,i) C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
        return 0;
    }
    struct bigmat{
        mat g,v[N];int len;
        inline int clear() { rep(i,0,T) v[i].clear();return len=0; }
        inline bigmat operator*(const bigmat &b)const
        {
            const bigmat &a=*this;static bigmat res;res.clear();
            if(!a.len) return b;res.g=a.g*b.g;
            rep(i,mi[0]=1,T) mi[i]=(lint)mi[i-1]*a.len%mod;
            rep(t,0,T)
            {
                rep(j,0,t) res.v[t]+=(lint)C[t][j]*mi[t-j]%mod*b.v[j];
                res.v[t]*=g,res.v[t]+=a.v[t];
            }
            return res.len=a.len+b.len,res;
        }
        inline bigmat operator*=(const bigmat &b) { return (*this)=(*this)*b,*this; }
        inline bigmat operator+(const bigmat &b)
        {
            static bigmat res;res=*this;
            rep(i,0,T) res.v[i]+=b.v[i];
            return res;
        }
        inline bigmat operator+=(const bigmat &b) { return (*this)=(*this)+b,*this; }
        inline int& operator()(int x,int y,int z) { return v[x](y,z); }
    };
}using BIGMAT::bigmat;bigmat G,ans;
inline int fast_pow(bigmat &x,int k) { for(;k;k>>=1,x*=x) if(k&1) ans*=x;return 0; }
int main()
{
    int n=inn(),k=inn(),q=inn(),T=inn();
    MAT::_init(n);rep(i,1,n) rep(j,1,n) g(i,j)=inn();
    if(k<=1) { while(q--) printf("0\n");return 0; }
    rep(i,0,T) ans.v[i]=I,G.v[i]=g;ans.g=I,G.g=g,ans.len=0,G.len=1;
    BIGMAT::_init(T),fast_pow(G,k-1);
    for(int x,y;q;q--) x=inn(),y=inn(),printf("%d\n",ans(T,x,y));
}

#include<bits/stdc++.h> using namespace std; #define mod 2017 typedef int ll; typedef vector<ll> vec; typedef vector<vec> mat; mat operator*(const mat& a, const mat& b) { int n = a.size(); mat c(n, vec(n, 0)); for (int i = 0; i < n; i++) { for (int k = 0; k < n; k++) { if (a[i][k]) { for (int j = 0; j < n; j++) { if (b[k][j]) { c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % mod; } } } } } return c; } int n, m, q; int u, v; int s, t_val; int main() { ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); cin >> n >> m >> q; mat bas(n + 1, vec(n + 1, 0)); bas[0][0] = 1; for (int i = 1; i <= n; i++) { bas[i][0] = 1; bas[i][i] = 1; } for (int i = 0; i < m; i++) { cin >> u >> v; bas[u][v] = (bas[u][v] + 1) % mod; bas[v][u] = (bas[v][u] + 1) % mod; } vector<mat> pow2; pow2.push_back(bas); for (int k = 1; k <= 30; k++) { pow2.push_back(pow2[k - 1] * pow2[k - 1]); } while (q--) { cin >> s >> t_val; vec f(n + 1, 0); f[s] = 1; for (int k = 0; k <= 30; k++) { if (t_val & (1 << k)) { vec nf(n + 1, 0); for (int i = 0; i <= n; i++) { if (f[i]) { for (int j = 0; j <= n; j++) { nf[j] = (nf[j] + f[i] * pow2[k][i][j]) % mod; } } } f = nf; } } ll res = 0; for (int i = 0; i <= n; i++) { res = (res + f[i]) % mod; } cout << res << '\n'; } return 0; } 问题描述 加里敦星球的人们特别喜欢喝可乐。因而,他们的敌对星球研发出了一个可乐机器人,并且放在了加里敦星球的 1 号城市上。这个可乐机器人有三种行为: 停在原地,去下一个相邻的城市,自爆。它每一秒都会随机触发一种行为。现在给加里敦星球城市图,回答 q 次询问: 在第 0 秒时可乐机器人在 s 号城市,问经过了 t 秒,可乐机器人的状态序列有多少种可能的方案? 两个序列不同,当且仅当存在某个时刻,机器人所在的城市不同,或者一个已经自爆,另一个还没有 。 输入格式 第一行输入 3 个正整数 N,M,q,其中 N 表示城市个数,M 表示道路个数。 接下来 M 行输入 u,v ,表示 u,v 之间有一条双向道路。 接下来 q 行输入 s,t 。 输出格式 输出可乐机器人的行为方案数,答案可能很大,请输出对 2017 取模后的结果。 样例输入 3 2 1 1 2 2 3 1 2 样例输出 8 提示 1≤n,q≤100,0≤m≤10000,t≤109 x修正代码
最新发布
07-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值