链接:https://ac.nowcoder.com/acm/problem/24639
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld
题目描述
thewindandrainisinmywayandnevergoingawaythewindandrainisinmywayandnevergoingaway
你在一个有 n 个城市的国家中行走,城市从 1 到 n 依次编号
任意两个城市之间都有一条双向道路可以通行,且你可以花一天的时间从当前所在的城市到达任意一个别的城市
由于你比较闲的无聊,所以你不会连续两天都呆在同一个城市,也就是说每天你所在的城市都不相同(这句话的意思是,对于相邻的两天,你所在的城市应该不同)
一开始你在 1 号城市,求经过 k 天后你回到 1 号城市的方案数
当然如果不存在任意一种方案就输出 0 就好了
输入描述:
第一行两个整数 n,k
输出描述:
一行一个整数表示答案对 998244353 取模后的结果
示例1
输入
复制
1 1
输出
复制
0
备注:
maker.cpp如下: #include "bits/stdc++.h" using namespace std; int main() { srand((unsigned long long) new char); int n = int(8e8) + rand() % int(1e8); int k = int(8e8) + rand() % int(1e8); printf("%d %d\n", n, k); }
写出递推式就很简单了
a[i]为第i天能到达1,b[i]为第i天不能到达1(都是合法的情况)
则a[i]=b[i-1] (昨天不能到达,那么今天就可以走到1)
b[i]=a[i-1]*(n-1)+b[i-1]*(n-2) (昨天能到达1,那么今天走除1外的(n-1) 加上 昨天不能到达,那么走除1和昨天走过的(n-2))
这样用个矩阵快速幂,然后把n=1的情况判掉就行了
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const ll mod = 998244353;
struct rt{
ll a[4][4];
rt(){memset(a,0,sizeof(a));}
rt operator *(const rt b){
rt res;
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
for(int k=0;k<2;k++){
// cout<<res.a[i][j]<<endl;
res.a[i][j]=(res.a[i][j]+a[i][k]*b.a[k][j]%mod)%mod;
// cout<<res.a[i][j]<<endl;
}
}
}
return res;
}
};
rt q_pow(rt A,ll b){
rt res;
for(int i=0;i<2;i++)res.a[i][i]=1;
while(b){
if(b&1)res=res*A;
A=A*A; b>>=1;
}
return res;
}
int main(){
ll n,k;
cin>>n>>k;
if(n==1){cout<<0<<endl;return 0;}
rt A,B;
A.a[0][0]=0; A.a[0][1]=n-1;
A.a[1][0]=1; A.a[1][1]=n-2;
B=q_pow(A,k);
cout<<B.a[0][0]<<endl;
return 0;
}