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
样例一:10 3 3
样例二:5 2 3
样例三:10 2 4
样例二:5 2 3
样例三:10 2 4
Sample Output
1
3
81
3
81
HINT
【样例说明】
样例一的可行方案如下: (1,4,7,10),(2,5,8),(3,6,9)
样例二的可行方案如下: (1,3,5),(2,4) (1,3,4),(2,5) (1,4),(2,3,5)
P<=10 , K <=8
解题思路:因为状态不多,所以将m+1看成一个整体,然后
枚举出所用可能的情况(dfs)并且状压记录下那些状态可以到哪个状态建立矩阵,
然后矩阵快速幂就可以了。
(细节坑死了。。。)
#include<cstdio>
#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);
}
#include<cstdio>
#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);
}