yyy loves Maths VII

题目描述
一群同学在和yyy玩一个游戏

每次,他们会给yyy n张卡片,卡片上有数字,所有的数字都是"幸运数字",我们认为第i张卡片上数字是ai

每次yyy可以选择向前走ai步并且丢掉第i张卡片

当他手上没有卡片的时候他就赢了

但是呢,大家对"厄运数字"的位置布置下了陷阱,如果yyy停在这个格子上,那么他就输了

(注意:即使到了终点,但是这个位置是厄运数字,那么也输了)

现在,有些同学开始问:

yyy有多大的概率会赢呢?

大家觉得这是个好问题

有人立即让yyy写个程序

“电脑运行速度很快!24的阶乘也不过就620448401733239439360000,yyy你快写个程序来算一算”

yyy表示很无语,他表示他不想算概率,最多算算赢的方案数,而且是%1,000,000,007以后的值

大家都不会写程序,只好妥协

但是这时候yyy为难了,24!太大了,要跑好长时间.

他时间严重不够!需要你的帮助!

由于yyy人格分裂,某个数字可能既属于幸运数字又属于厄运数字。

输入格式
第一行n

下面一行n张卡片

第三行m 表示yyy的厄运数字个数(最多2个)

最后一行是m个厄运数字

输出格式
方案数%1,000,000,007

输入输出样例
输入 #1复制
8
1 3 1 5 2 2 2 3
0
输出 #1复制
40320
输入 #2复制
24
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
2
10 15
输出 #2复制
0
说明/提示
数据范围:

10%的数据n<=10

50%的数据n<=23

100%的数据n<=24


听说这道题比较卡常,但是为什么我最高才300ms。。。。。。

看到n只有24,明显的爆搜,可能我剪枝有问题,然后TLE。。。。最后直接状压DP了。

我们存一下当前状态的个数,当前状态的距离即可。

对于每个状态,我们需要提取每个1出来,直接lowbit就好了,不然复杂度是很卡的。


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
#define lowbit(x) (x&(-x))
using namespace std;
const int mod=1e9+7;
int n,m,e[2],dp[1<<24],d[1<<24];
signed main(){
	cin>>n;
	for(int i=0;i<n;i++)	cin>>d[1<<i];
	cin>>m;
	for(int i=0;i<m;i++)	cin>>e[i];
	dp[0]=1;
	for(int i=1;i<(1<<n);i++){
		d[i]=d[i^lowbit(i)]+d[lowbit(i)];
		if(d[i]==e[0]||d[i]==e[1])	continue;
		for(int j=i,k;j;j^=k){
			k=lowbit(j);	dp[i]+=dp[i^k];	if(dp[i]>=mod)	dp[i]-=mod;
		}
	}
	cout<<dp[(1<<n)-1];
	return 0;
}
发布了416 篇原创文章 · 获赞 228 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/103890545
yyy
今日推荐