這題題面並不是很嚴密啊。。應該說明當石子在走出棋盤邊界判定為移除,不然有可能會被理解為不做行動。
操作次數很大,直接模擬行不通。
我們想辦法將棋盤上所有格仔的一次操作轉化為矩陣上的變換來解決。
考慮將棋盤上的格仔轉化為編號,也就是 \(i\) 行 \(j\) 列的格仔編號為 \((i-1)m + j\)。我們建立乙個 \(n\times m + 1\) 行 \(1\) 列的矩陣,其中最後一行值為 \(1\),其餘為 \(0\)。
\[\begin
0\\0
\\ \vdots
\\ 1
\end
\]接下來考慮如何將三種操作對應到矩陣上的操作中:
下面的步驟是構造變換的矩陣,也就是考慮左乘的矩陣的構造。(記矩陣為 \(op\))
// problem: 石頭遊戲
// contest: acwing
// url:
// memory limit: 64 mb
// time limit: 1000 ms
// // powered by cp editor (
#includeusing namespace std;
#define debug(x) cerr << #x << ": " << (x) << endl
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define int long long
inline void read(int &x)
while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
x*=s;
}struct mat
mat(int _n, int _m)
void init(int _n, int _m)
void i()
mat operator * (const mat &o)const
return res;
}mat fpow(int p)
void solve()
rep(i,1,act)
int nm=n*m;
mat op[65];
rep(i,1,60) op[i].init(nm+1, nm+1), op[i].w[nm+1][nm+1]=1;
rep(k,1,60)
else if(type!='d')
} }
mat op(nm+1, nm+1);
op.i();
rep(i,1,60) op=op[i]*op;
op=op.fpow(t/60);
mat res(nm+1, 1); res.w[nm+1][1]=1;
res=op*res;
rep(i,1,t%60) res=op[i]*res;
res.solve();
return 0;
}
取石頭遊戲 博弈論 數學規律
兩個足夠聰明的人玩輪流取石頭的遊戲,誰取到最後乙個石頭誰就贏了,他們一次只能取1個 3個 7個或 8個石頭,寫一程式判斷 n個石頭時先取的人是輸還是贏。輸入格式 多組輸入,乙個整數 n,其值不超過 10000000。輸出格式 如果先取的人贏,請以單獨一行輸出 1,否則輸出0。輸入樣例 1 10300...
牛客 復讀陣列(矩陣加速 數學)
有乙個長為n k的陣列,它是由長為n的陣列a1,a2,an重複k次得到的。定義這個陣列的乙個區間的權值為它裡面不同的數的個數,現在,你需要求出對於這個陣列的每個非空區間的權值之和。答案對109 7取模。第一行兩個整數n和k。接下來一行n個整數,第i個整數為ai。輸出乙個整數,表示答案。示例1輸入 2...
模板 矩陣加速(數列)(矩陣加速遞推)
a 1 a 2 a 3 1 a x a x 3 a x 1 x 3 求a數列的第n項對1000000007 10 9 7 取餘的值。輸入格式 第一行乙個整數t,表示詢問個數。以下t行,每行乙個正整數n。輸出格式 每行輸出乙個非負整數表示答案。矩陣加速裸題 和我的前一篇基本一模一樣 只不過改變了要乘的...