把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

CF525E Anya and Cubes

题面传送门
一道题数据范围那么小肯定考虑搜索。
但是这个数据范围稍微偏大了一点。
所以就可以折半搜索。\(O(3^{\frac{n}{2}})n\)
但是这样卡不进去。
我们的map一般是这么写的

ans+=f[i][k-z];

然后我换成这么写直接300ms

if(f[i].count(k-z))ans+=f[i][k-z];

这是为什么呢?我翻看了stl的map那个函数,发现=是被重定义,这样写是\(O(logn)\)的。
但是count这个函数是这么写的。

count(const key_type& __x) const
      { return _M_t.find(__x) == _M_t.end() ? 0 : 1; }

这东西常数就很小了。
代码实现:

#include<cstdio>
#include<map>
#include<algorithm>
using namespace std;
int n,a[139],m;
long long s,k,po[39],b[39];
long long ans;
map<long long ,int> f[39];
inline void dfs1(const int & x,const int &y,const long long &z){
	if(z>k) return; 
	if(x==n/2+1) {f[y][z]++;return;}
	dfs1(x+1,y,z);dfs1(x+1,y,z+a[x]);
	if(a[x]<=18&&y<m) dfs1(x+1,y+1,z+b[x]);
}
inline void dfs2(const int &x,const int &y,const long long &z){
	if(z>k) return; 
	if(x==n+1){
		for(register int i=0;i<=m-y;i++) if(f[i].count(k-z))ans+=f[i][k-z];
		return;
	}
	dfs2(x+1,y,z);dfs2(x+1,y,z+a[x]);
	if(a[x]<=18&&y<m) dfs2(x+1,y+1,z+b[x]);
}
int main(){
	register int i;
	freopen("1.in","r",stdin);
	po[1]=1;
	for(i=2;i<=19;i++)po[i]=po[i-1]*i;
	scanf("%d%d%lld",&n,&m,&k);
	for(i=1;i<=n;i++) scanf("%d",&a[i]);
	sort(a+1,a+n+1);
	for(i=1;i<=n;i++) b[i]=a[i]>18?0:po[a[i]];
	dfs1(1,0,0);
	dfs2(n/2+1,0,0);
	printf("%lld\n",ans);
} 
posted @ 2021-01-29 22:31  275307894a  阅读(70)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end