今天打了CCPC-Wannafly & Comet OJ 夏季歡樂賽(2019)
對退休老年黨太友好了!碼量小的驚人,且思路簡單,瞎捏捏就粗來了。
鑑於太久沒有更博了,我今天要更博!
感覺太久沒打代碼了,假期回去會被錘爆吧!我要趁工作之餘悄悄代碼,不能稱爲一條競賽鹹魚!
E
可以推導出當位於前k格的時候,到達終點的期望都是一樣的。
後面就可以直接用矩乘推出來了。
(在網上扒拉代碼扒拉了好久……沒板子實慘
#include<iostream>
#include<string.h>
#include<math.h>
#include<vector>
#include<algorithm>
#define ll long long
using namespace std;
const long long N=30;
const long long mod=1000000007;
long long tmp[N][N];
void multi(long long a[][N], long long b[][N], long long n){
memset(tmp,0,sizeof tmp);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
for(int k=0;k<n;k++)
tmp[i][j]=(tmp[i][j]+a[i][k]*b[k][j])%mod;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
a[i][j]=tmp[i][j];
}
long long res[N][N];
void Pow(long long a[][N],long long n, long long size){
memset(res,0,sizeof (res) );//n是冪,N是矩陣大小
for(int i=0;i<size;i++) res[i][i]=1;
while(n){
if(n&1)
multi(res,a,size);//res=res*a;複製直接在multi裏面實現了;
multi(a,a,size);//a=a*a
n>>=1;
}
}
void exgcd(ll a,ll b,ll& d,ll& x,ll& y)
{
if(!b) { d = a; x = 1; y = 0; }
else{ exgcd(b, a%b, d, y, x); y -= x*(a/b); }
}
ll inv(ll a, ll p)
{
ll d, x, y;
exgcd(a, p, d, x, y);
return d == 1 ? (x+p)%p : -1;
}
long long a[N][N];
int main(){
ll n,k;
cin>>n>>k;
for (int i=1;i<k;i++){
a[i][i-1]=1;
}
ll x=inv(k,mod);
for (int i=0;i<k;i++){
a[i][k-1]=x;
}
a[k][k-1]=a[k][k]=1;
/*
for (int i=0;i<k;i++){
for (int j=0;j<k;j++){
cout<<a[i][j]<<" ";
}
cout<<endl;
}
*/
Pow(a,n-1,k+1);
/*
for (int i=0;i<k+1;i++){
for (int j=0;j<k+1;j++){
cout<<res[i][j]<<" ";
}
cout<<endl;
}
*/
ll ans=0;
for (int i=0;i<k;i++){
ans=(ans+k*res[i][0])%mod;
}
ans=(ans+res[k][0])%mod;
cout<<ans<<endl;
}