题意:假设有n层电梯,现在你在x层,第d层是神奇的一层,因为你从第x层到第y层必须满足条件|x - y| < |x - b|,每走一步记下y,求走k步有多少种长度为k-1不同序列。
。。。过了蛮久再看此题有点陌生了。。。
有些题还是需要回顾一下,不然写了相当没写。
其实转态的转移题目已经说了,我们可以从当前点出发,在所有能从该点走到的点累加走到当前点的方案数,当然对于每一个当前点,我们去枚举所有的能到的点必然会超时,于是可以用前缀和的思想,假设当前点d(方案数为t)可以到达[x,y],我们先在sum【y】+=t;sun【x-1】-=t;这样不就是给区间【x,y】统一加上一个值吗,无需遍历该区间,然后因为是前缀合,从后到前遍历数组,我们通过sum数组求得更新后的第当前部每一点方案数。
第二种方案,逆推,我们求当前点y的方案数,可以从合法的上一步的x点推得而来,同样利用前缀和。
方案一:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int mod=1e9+7;
long long f[5][5010];
long long s[5010];
int main()
{
int n,i,j,a,b,k,t;
long long ans,tmp;
while(scanf("%d%d%d%d",&n,&a,&b,&k)!=EOF)
{
ans=0;
memset(f,0,sizeof(f));
f[0][a]=1;
memset(s,0,sizeof(s));
if(b>a)
{
for(j=1;j<=k;j++){
for(i=b-1;i>=1;i--)
{
tmp=0;
if(f[(j-1)%2][i])
{
t=max(1,2*i-(b-1));
s[t-1]=(s[t-1]-f[(j-1)%2][i]+mod)%mod;
s[i-1]=(s[i-1]+f[(j-1)%2][i])%mod;
s[i]=(s[i]-f[(j-1)%2][i]+mod)%mod;
s[b-1]=(s[b-1]+f[(j-1)%2][i])%mod;
}
}
for(i=b-1;i>=1;i--)
{
tmp=(tmp+s[i])%mod;
s[i]=0;
f[(j)%2][i]=tmp;
}
}
for(i=1;i<b;i++)
ans=(ans+f[(j+1)%2][i])%mod;
printf("%I64d\n",ans);
}
else {
for(j=1;j<=k;j++){
for(i=n;i>b;i--)
{
tmp=0;
if(f[(j-1)%2][i])
{
t=min(n,2*i-(b+1));
s[t]=(s[t]+f[(j-1)%2][i])%mod;
s[i]=(s[i]-f[(j-1)%2][i]+mod)%mod;
s[i-1]=(s[i-1]+f[(j-1)%2][i]+mod)%mod;
s[b]=(s[b]-f[(j-1)%2][i])%mod;
}
}
for(i=n;i>=b+1;i--)
{
tmp=(s[i]+tmp)%mod;
s[i]=0;
f[j%2][i]=tmp;
}
}
for(i=n;i>b;i--)
ans=(ans+f[(j+1)%2][i])%mod;
printf("%I64d\n",ans);
}
}
}
方案二:
1
#include<bits/stdc++.h>
#define mod 1000000007
using namespace std;
int n,a,b,k,f[50010],p[50010],i,j;
int main()
{
scanf("%d%d%d%d",&n,&a,&b,&k);f[a]=1;
for(i=1;i<=k;i++)
{
for(j=1;j<=n;j++)p[j]=(p[j-1]+f[j])%mod;
for(j=1;j<=n;j++)
{
if(j<b)f[j]=(p[(j+b-1)/2]-f[j]+mod)%mod;
if(j>b)f[j]=((p[n]-p[(j+b)/2]+mod)%mod-f[j]+mod)%mod;
}
}
for(j=1;j<=n;j++)p[j]=(p[j-1]+f[j])%mod;
printf("%d",p[n]);
}
2
#include <stdio.h>
#include <string.h>
const int M=1000000007;
int n,a,b,k,v[2][5432],*p=v[0],*q=v[1];
int main(){
scanf("%d%d%d%d",&n,&a,&b,&k);
if(a>b)a=n-a+1,b=n-b+1;
p[a]=1;
for(int i=0;i<k;++i){
for(int j=1;j<b;++j)q[j]=M-p[j],(p[j]+=p[j-1])%=M;
for(int j=1;j<b;++j)(q[j]+=p[(j+b-1)/2])%=M;
int* w=p;p=q,q=w;
}
int s=0;
for(int i=1;i<b;++i)(s+=p[i])%=M;
printf("%d\n",s);
}