Description
傑傑是魔法界的一名傳奇人物。他對魔法具有深刻的洞察力,驚人的領悟力,以及令人歎爲觀止的創造力。自從他從事魔法競賽以來,短短几年時間,就已經成爲世界公認的實力最強的魔法選手之一。更讓人驚歎的是,他幾乎沒有藉助外界力量,完全憑藉自己的努力達到了普通人難以企及的高度。在最近的世界魔法奧林匹克競賽上,他使用高超的魔法本領,一路過關斬將,在最後時刻一舉擊敗了前冠軍“旅行者”,獲得了魔法界最高的榮耀:女神獎盃!女神獎盃可不是一個普通的獎盃,她能夠幫傑傑實現一個願望。
傑傑本着實事求是的態度,審時度勢,向女神獎盃提出了自己的願望:想要一個女性朋友。
傑傑的願望實現了,可是女性朋友卻和他不在一個城市。傑傑想要知道:如果要到達女性朋友的所在城市,有多少種方案供他選擇?
傑傑所在的世界有 個城市,從 到 進行編號。任意兩個城市都通過有向道路連接。
每個城市 有 個入點權:,有 個出點權:。
對於任意兩個城市 ( 可以等於 ), 到 的道路條數爲 條。
傑傑有 次詢問,每次詢問由三元組 構成,詢問從 城市通過不超過 條道路到達 城市的方案數。
爲了溫柔的傑傑和他的女性朋友的美好未來,幫助他解答這個問題吧。
input
第一行讀入兩個正整數 ,,含義如題所示。接下來 行每行 個整數,第 行代表第 個城市,前 個整數代表 號城市的出點權,後 個整數代表i號城市的入點權: 。
接下來一個整數 ,表示 個詢問。
接下來 行,每行三個整數: ,詢問從 城市通過不超過 條道路到達 城市的方案數。
將每個方案所經過的道路,按順序寫成一個序列(序列可以爲空)。兩個方案不同,當且僅當他們的道路序列不完全相同。
output
對於每個詢問,輸出一個方案數。由於答案可能太大,輸出其除以 後的餘數。
Data
對於 的數據,。
對於另外 的數據,。
對於 的數據,。
Solution
很明顯的矩陣快速冪,發現如果是整個矩陣拿去搞的話 就爆炸了,考慮可以把轉移拆開,只有第一次和最後一次是 的轉移,中間的都是 的轉移,直接做就好了。
Code
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <queue>
#include <set>
#include <stack>
#define R register
#define ll long long
#define db double
#define sqr(_x) (_x) * (_x)
#define Cmax(_a, _b) ((_a) < (_b) ? (_a) = (_b), 1 : 0)
#define Cmin(_a, _b) ((_a) > (_b) ? (_a) = (_b), 1 : 0)
#define Max(_a, _b) ((_a) > (_b) ? (_a) : (_b))
#define Min(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#define Abs(_x) (_x < 0 ? (-(_x)) : (_x))
using namespace std;
namespace Dntcry
{
inline int read()
{
R int a = 0, b = 1; R char c = getchar();
for(; c < '0' || c > '9'; c = getchar()) (c == '-') ? b = -1 : 0;
for(; c >= '0' && c <= '9'; c = getchar()) a = (a << 1) + (a << 3) + c - '0';
return a * b;
}
inline ll lread()
{
R ll a = 0, b = 1; R char c = getchar();
for(; c < '0' || c > '9'; c = getchar()) (c == '-') ? b = -1 : 0;
for(; c >= '0' && c <= '9'; c = getchar()) a = (a << 1) + (a << 3) + c - '0';
return a * b;
}
const int Maxn = 1010, Maxk = 21, Mod = 1000000007;
int n, p, m, u, v, d, tmp, in[Maxk][Maxn], out[Maxn][Maxk];
struct Matrix
{
int v[Maxk][Maxk];
Matrix() { memset(v, 0, sizeof(v)); }
Matrix operator + (const Matrix &b) const
{
R Matrix c;
for(R int i = 1; i <= p; i++)
for(R int j = 1; j <= p; j++)
c.v[i][j] = (v[i][j] + b.v[i][j]) % Mod;
return c;
}
Matrix operator * (const Matrix &b) const
{
R Matrix c;
for(R int i = 1; i <= p; i++)
for(R int k = 1; k <= p; k++) if(v[i][k])
for(R int j = 1; j <= p; j++) if(b.v[k][j])
c.v[i][j] = (c.v[i][j] + 1ll * v[i][k] * b.v[k][j] % Mod) % Mod;
return c;
}
}E, A, Now, Ans;
void Calc(R int x)
{
if(x == 1) { Now = Ans = A; }
else
{
Calc(x >> 1);
Ans = Ans * (E + Now), Now = Now * Now;
if(x & 1) Now = Now * A, Ans = Ans + Now;
}
}
int Main()
{
n = read(), p = read();
for(R int i = 1; i <= n; i++)
{
for(R int j = 1; j <= p; j++) out[i][j] = read() % Mod;
for(R int j = 1; j <= p; j++) in[j][i] = read() % Mod;
}
for(R int i = 1; i <= p; i++) E.v[i][i] = 1;
for(R int i = 1; i <= p; i++)
for(R int k = 1; k <= n; k++) if(in[i][k])
for(R int j = 1; j <= p; j++) if(out[k][j])
A.v[i][j] = (A.v[i][j] + 1ll * in[i][k] * out[k][j] % Mod) % Mod;
m = read();
while(m--)
{
u = read(), v = read(), d = read();
tmp = (u == v);
if(d) for(R int i = 1; i <= p; i++) tmp = (tmp + 1ll * out[u][i] * in[i][v] % Mod) % Mod;
if(d > 1)
{
Calc(d - 1);
for(R int i = 1; i <= p; i++)
for(R int j = 1; j <= p; j++)
tmp = (tmp + 1ll * out[u][i] * in[j][v] % Mod * Ans.v[i][j] % Mod) % Mod;
}
printf("%d\n", tmp);
}
return 0;
}
}
int main()
{
return Dntcry :: Main();
}