[HNOI2002]公交车路线 题解

111 阅读1分钟

题目链接

思路

设顺时针走为11,逆时针走为00,题目就转化为了求有多少个长度为nn0101串,满足除去整个串作为前缀的任意一个前缀中0,10,1数目的差值不超过33,且整个串中0,10,1数目差值为44。考虑dp,设fi,jf_{i,j}为长度为ii的串中0,10,1差值为jj的串的个数,状态转移就很容易写出来了,具体可以看代码,由于每次转移只需要i1i-1的信息,所以可以用两个数组滚动优化一下。

代码

#include<bits/stdc++.h>
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
#define bl(u,i) for(int i=head[u];i;i=e[i].nxt)
#define en puts("")
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll> 
typedef long long ll;
typedef double db;
using namespace std;
const ll INF=0x3f3f3f3f;
void read() {}
void OP() {}
void op() {}
template <typename T, typename... T2>
inline void read(T &_, T2 &... oth)
{
    int __=0;
    _=0;
    char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
            __=1;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        _=_*10+ch-48;
        ch=getchar();
    }
    _=__?-_:_;
    read(oth...);
}
template <typename T>
void Out(T _)
{
    if(_<0)
    {
        putchar('-');
        _=-_;
    }
    if(_>=10)
       Out(_/10);
    putchar(_%10+'0');
}
template <typename T, typename... T2>
inline void OP(T _, T2... oth)
{
	Out(_);
	putchar('\n');
	OP(oth...);
}
template <typename T, typename... T2>
inline void op(T _, T2... oth)
{
	Out(_);
	putchar(' ');
	op(oth...);
}
/*#################################*/
const ll N=100,P=1000;
ll n,res;
ll pre[N],f[N];
int main()
{
	read(n);
	pre[1]=pre[4]=1;
	rep(i,2,n-1)
	{
		f[0]=(pre[1]+pre[4])%P;
		f[1]=(pre[0]+pre[2])%P;
		f[2]=(pre[1]+pre[3])%P;
		f[3]=pre[2];
		f[4]=(pre[0]+pre[5])%P;
		f[5]=(pre[4]+pre[6])%P;
		f[6]=pre[5];
		rep(j,0,6)
			pre[j]=f[j];
	}
	OP((f[6]+f[3])%P);
}