CCPC-Wannafly & Comet OJ 夏季欢乐赛(2019)

今天打了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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值