2004: [Hnoi2010]Bus 公交線路
Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 576 Solved: 406
[Submit][Status][Discuss]
Description
小Z所在的城市有N個公交車站,排列在一條長(N-1)km的直線上,從左到右依次編號爲1到N,相鄰公交車站間的距離均爲1km。 作爲公交車線路的規劃者,小Z調查了市民的需求,決定按下述規則設計線路: 1. 設共K輛公交車,則1到K號站作爲始發站,N-K+1到N號臺作爲終點站。 2. 每個車站必須被一輛且僅一輛公交車經過(始發站和終點站也算被經過)。 3. 公交車只能從編號較小的站臺駛往編號較大的站臺。 4. 一輛公交車經過的相鄰兩個站臺間距離不得超過Pkm。 在最終設計線路之前,小Z想知道有多少種滿足要求的方案。由於答案可能很大,你只需求出答案對30031取模的結果。
Input
僅一行包含三個正整數N K P,分別表示公交車站數,公交車數,相鄰站臺的距離限制。N<=10^9,1<P<=10,K<N,1<K<=P
Output
僅包含一個整數,表示滿足要求的方案數對30031取模的結果。
Sample Input
樣例二:5 2 3
樣例三:10 2 4
Sample Output
3
81
HINT
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int n,m,k,cnt,ans,uoo,sug,pu;
const int MOD=30031;
int dui[430],zan[430],c[430];
int ch[430][430],zh[430][430];
int qu[20480];
bool b[11];
inline int read()
{
char y; int x=0,f=1; y=getchar();
while (y<'0' || y>'9') {if (y=='-') f=-1; y=getchar();}
while (y>='0' && y<='9') {x=x*10+int(y)-48; y=getchar();}
return x*f;
}
void dfs1(int sum,int opp,int now,int cg)
{
if (now==m+1-k)
{
if ((sum&uoo)!=0) return;
int og=sum>>(m+1-k);
if (qu[og]==0)
{
++cnt; dui[cnt]=og; qu[og]=cnt; ch[cnt][opp]+=1;
memset(b,true,sizeof(b)); dfs1(og,cnt,0,0); memset(b,false,sizeof(b));return;
}
ch[qu[og]][opp]+=1; return;
}
for (int i=cg+1;i<=m+1+m+1-k;++i)
{
int ty=(1<<(i-1));
if ((sum&ty)!=0)
{
for (int j=1;j<=m+1-k;++j)
if (b[j] && j+1-i<=0 && i<=j+m+1)
{
b[j]=false;
dfs1(sum-ty+(1<<(j+m)),opp,now+1,i);
b[j]=true;
}
}
}
}
void work()
{
while (sug!=0)
{
if (sug%2==1)
{
memset(zan,0,sizeof(zan));
for (int i=1;i<=cnt;++i)
for (int j=1;j<=cnt;++j)
{
zan[i]=(zan[i]+ch[i][j]*c[j])%MOD;
}
memcpy(c,zan,sizeof(zan));
}
memset(zh,0,sizeof(zh));
for (int i=1;i<=cnt;++i)
for (int j=1;j<=cnt;++j)
for (int k=1;k<=cnt;++k)
{
zh[i][j]=(zh[i][j]+ch[i][k]*ch[k][j])%MOD;
}
memcpy(ch,zh,sizeof(zh));
sug=sug/2;
}
}
int main()
{
n=read(); k=read(); m=read(); uoo=0; pu=1;
for (int i=1;i<=m+1-k;++i)
{
uoo=uoo+(1<<(i-1));
pu=(pu*i)%MOD;
}
memset(ch,0,sizeof(ch)); memset(c,0,sizeof(c));
cnt=0; int sum=0;
for (int i=1;i<=k;++i)
{
sum=sum+(1<<(i-1));
}
sug=(n-k)/(m-k+1);
sum=sum<<(m-k+1); ++cnt; dui[cnt]=sum; qu[sum]=cnt;
memset(b,true,sizeof(b));
dfs1(sum,1,0,0);
c[1]=1;
work();
ans=0;
int op=0; int oh=(n-k)%(m-k+1);
for (int i=1;i<=k-oh;++i)
op=op+(1<<(i-1));
op=op<<(m+1-k+oh);
for (int i=1;i<=cnt;++i)
if ((dui[i]&op)==op && (dui[i]%2==0))
{
int oq=1; int ji=0;
if (oh!=0)
for (int j=1;j<=m+1;++j)
{
int ty=(1<<(j-1));
if ((dui[i]&ty)!=0)
{
oq=(oq*(min(oh,j-1)-ji))%MOD; ++ji;
}
if (ji==oh) break;
}
ans=(ans+c[i]*oq)%MOD;
}
printf("%d",ans);
}
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int n,m,k,cnt,ans,uoo,sug,pu;
const int MOD=30031;
int dui[430],zan[430],c[430];
int ch[430][430],zh[430][430];
int qu[20480];
bool b[11];
inline int read()
{
char y; int x=0,f=1; y=getchar();
while (y<'0' || y>'9') {if (y=='-') f=-1; y=getchar();}
while (y>='0' && y<='9') {x=x*10+int(y)-48; y=getchar();}
return x*f;
}
void dfs1(int sum,int opp,int now,int cg)
{
if (now==m+1-k)
{
if ((sum&uoo)!=0) return;
int og=sum>>(m+1-k);
if (qu[og]==0)
{
++cnt; dui[cnt]=og; qu[og]=cnt; ch[cnt][opp]+=1;
memset(b,true,sizeof(b)); dfs1(og,cnt,0,0); memset(b,false,sizeof(b));return;
}
ch[qu[og]][opp]+=1; return;
}
for (int i=cg+1;i<=m+1+m+1-k;++i)
{
int ty=(1<<(i-1));
if ((sum&ty)!=0)
{
for (int j=1;j<=m+1-k;++j)
if (b[j] && j+1-i<=0 && i<=j+m+1)
{
b[j]=false;
dfs1(sum-ty+(1<<(j+m)),opp,now+1,i);
b[j]=true;
}
}
}
}
void work()
{
while (sug!=0)
{
if (sug%2==1)
{
memset(zan,0,sizeof(zan));
for (int i=1;i<=cnt;++i)
for (int j=1;j<=cnt;++j)
{
zan[i]=(zan[i]+ch[i][j]*c[j])%MOD;
}
memcpy(c,zan,sizeof(zan));
}
memset(zh,0,sizeof(zh));
for (int i=1;i<=cnt;++i)
for (int j=1;j<=cnt;++j)
for (int k=1;k<=cnt;++k)
{
zh[i][j]=(zh[i][j]+ch[i][k]*ch[k][j])%MOD;
}
memcpy(ch,zh,sizeof(zh));
sug=sug/2;
}
}
int main()
{
n=read(); k=read(); m=read(); uoo=0; pu=1;
for (int i=1;i<=m+1-k;++i)
{
uoo=uoo+(1<<(i-1));
pu=(pu*i)%MOD;
}
memset(ch,0,sizeof(ch)); memset(c,0,sizeof(c));
cnt=0; int sum=0;
for (int i=1;i<=k;++i)
{
sum=sum+(1<<(i-1));
}
sug=(n-k)/(m-k+1);
sum=sum<<(m-k+1); ++cnt; dui[cnt]=sum; qu[sum]=cnt;
memset(b,true,sizeof(b));
dfs1(sum,1,0,0);
c[1]=1;
work();
ans=0;
int op=0; int oh=(n-k)%(m-k+1);
for (int i=1;i<=k-oh;++i)
op=op+(1<<(i-1));
op=op<<(m+1-k+oh);
for (int i=1;i<=cnt;++i)
if ((dui[i]&op)==op && (dui[i]%2==0))
{
int oq=1; int ji=0;
if (oh!=0)
for (int j=1;j<=m+1;++j)
{
int ty=(1<<(j-1));
if ((dui[i]&ty)!=0)
{
oq=(oq*(min(oh,j-1)-ji))%MOD; ++ji;
}
if (ji==oh) break;
}
ans=(ans+c[i]*oq)%MOD;
}
printf("%d",ans);
}