您的位置:首页 > 其它

Codeforces Round #274 (Div. 2)E. Riding in a Lift

2015-08-07 19:50 411 查看
题意:假设有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
-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
);
}

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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: