列表

详情


NC212207. 旅行没有商问题

描述

我的歌曲只好向陌生的众人倾诉,
他们即使喝彩也会令我心伤,
当年赏识过我的歌诗的知音,
纵然在世亦不知向何方飘零。
                            ——歌德《浮士德》
剧情版题面:(温馨提示:赶时间的话,简化版见下面)
然而出题人可没工夫读歌德,出题人忙得很,他天天都要照顾女友(我可没说是本题出题人)
他现在又在计划寒假带着女友去旅行了,他们决定旅游d天,有n个可选城市(分别编号为1,2,3...n),其中有k个是出题人想去的城市(而对于出题人的女友,出门旅游=逛吃逛吃,所以她并不介意去哪)
在这d天中,他们每天都要一起待在一个城市,由于出题人喜欢赶路,他们不会在连续两天待在同一个城市,但可以在一个城市旅游若干天。
他们可以选择任意一个城市作为旅行的出发地和结束地。
当且仅当两座城市之间修筑有公路(任意两座城市之间不会修筑两条及以上的公路,一座城市不会修筑与自己相连的公路)时,他们可以从一座城市前往另一座城市。
出题人可爱的女友答应陪他在所有k个想去的城市旅游,所以合法的旅游方案中k个出题人想去的城市必须全部经过(经过至少一次,多次不限9
出题人太忙了,所以他想让你帮他求出全部合法方案数对109+7取余的结果(就是方案数除以109+7的余数)
简化题面

给出n个点,m条边的无向图。满足无重边、自环,不保证连通。某人在图上依次访问d个节点(即所经过的所有节点构成的序列长度为d)。n个点中有k个点必须至少经过一次。起点、终点任选。求满足条件的方案数对109+7取模的值

输入描述

第一行四个整数n,m,d,k,分别表示可选城市数量(图上点数),公路总数(无向边边数),旅游天数(访问节点个数),出题人想去的城市数量(必经节点个数)

第二行k个整数,表示出题人想去的各个城市的编号(各必经节点编号)

第三行到第m+2行,每行两个整数x,y,表示编号为x,y的城市之间修筑有一条公路(表示x,y两点间存在一条无向边)

输出描述

输出一个整数表示答案

示例1

输入:

4 5 4 2
1 2
1 2
1 3
2 3
2 4
3 4

输出:

36

说明:

合法方案(举例):

3-1-2-4

3-1-2-3

2-3-1-3

非法方案(举例):

4-1-2-3(4,1之间不存在边)

3-4-2-3(必经点1未被经过)

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++11) 解法, 执行用时: 157ms, 内存消耗: 400K, 提交时间: 2020-12-26 18:22:49

#include <bits/stdc++.h>
#define rep(i,n) for ((i)=1;(i)<=(n);(i)++)
using namespace std;
const int mod=1e9+7;
int n,m,d,p,i,j,k;
struct mat{
	int a[24][24];
};
mat mul(mat x,mat y){
	mat z;int i,j,k;rep(i,n)rep(j,n){
		z.a[i][j]=0;rep(k,n)z.a[i][j]=(z.a[i][j]+x.a[i][k]*1ll*y.a[k][j])%mod;
	}
	return z;
}
mat pw(mat x,int y){
	mat z;int i,j;rep(i,n)rep(j,n)z.a[i][j]=(i==j);
	while(y){
		if(y&1)z=mul(z,x);
		y>>=1;x=mul(x,x);
	}
	return z;
}
int a[24],g[24][24],v[24];
int ans;
int main(){
	cin>>n>>m>>d>>p;
	for(i=0;i<p;i++){
		cin>>a[i];
	}
	rep(i,m){
		int x,y;cin>>x>>y;g[x][y]=g[y][x]=1;
	}
	for(i=0;i<(1<<p);i++){
		rep(j,n)v[j]=1;
		for(j=0;j<p;j++)if((i>>j)&1) v[a[j]]=0;
		mat tmp;
		rep(j,n)rep(k,n) tmp.a[j][k]=(g[j][k]&&v[j]&&v[k]);
		tmp=pw(tmp,d-1);
		int res=0;
		rep(j,n)rep(k,n)if(v[j]&&v[k]) res=(res+tmp.a[j][k])%mod;
		if(__builtin_popcount(i)&1) ans=(ans+mod-res)%mod; else (ans+=res)%=mod;
	}
	cout<<ans<<endl;
	return 0;
}

上一题