P5059 中国象棋
首先中国象棋是放在格点上的,所以先 样例因为这个看了好久没看懂
又由于每个卒只能攻击与其相邻的两个卒,所以容易发现行与行之间是独立的,所以只考虑一行中的情况。
对于每行至少放两个棋子的限制,可以先抛开不管,最后减去只放一个或不放的
设
因为
求出每一行的方案以后,根据乘法原理,总方案数为每行的方案数之积。
计算过程可能爆
时间复杂度
点击查看代码
#include <bits/stdc++.h> using namespace std; #define ll long long const ll SIZE = 200005; ll n, mod; inline ll rd(){ ll f = 1, x = 0; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); } return f*x; } inline void wt(ll x) { if(x<0) { putchar('-'); x=-x; } if(x>9) wt(x/10); putchar(x%10+'0'); } struct node{ ll o[2][2]; node(){ for(ll i = 0; i < 2; i++) for(ll j = 0; j < 2; j++) o[i][j] = 0; } }; node mul(node A, node B){ node jl; for(ll i = 0; i < 2; i++) for(ll j = 0; j < 2; j++) for(ll k = 0; k < 2; k++) jl.o[i][j] = (jl.o[i][j] + ((__int128)A.o[i][k] * B.o[k][j] % mod)) % mod; return jl; } node power(node x, ll y){ node jl; for(ll i = 0; i < 2; i++) jl.o[i][i] = 1; while(y){ if(y&1) jl = mul(jl, x); x = mul(x, x); y >>= 1; } return jl; } ll power(ll x, ll y){ ll jl = 1; while(y){ if(y&1) jl = ((__int128)jl * x) % mod; x = ((__int128)x * x) % mod; y >>= 1; } return jl; } int main(){ n = rd()+1, mod = rd(); if(n <= 2){ printf("0"); return 0; } node ans; ans.o[0][0] = ans.o[0][1] = ans.o[1][0] = 1; ans.o[1][1] = 0; ans = power(ans, n-1); ll jl = ((ans.o[0][0] + ans.o[0][1])%mod + (ans.o[1][0] + ans.o[1][1])%mod)%mod; jl = ((jl - n - 1) % mod + mod) % mod; wt(power(jl, n)); return 0; }
本文作者:Semorius
本文链接:https://www.cnblogs.com/Semorius/p/17538287.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步