题目描述
三教是第三教学楼的简称,也是由虚幻工作室开发的一款恐怖推理游戏,将在 2020 年一月在 Steam 上
推出第一个 Demo。
Kanade 正控制着人物玩着满是 bug 的偷跑版。在游戏中,一共有 n 个补给点,如果人物到达补给点
,将会获得体力 ai ,但是如果在这个补给点用一些操作触发 bug,将会获得体力 2^f(ai) ,其中 f(x) 表
示 x 的二进制表示中 1的个数,最牛的 bug 莫过于到达补给点之后你可以选择不要提供的体力,也就
是操作之后玩家将不会获得任何体力,Kanade 也掌握了这个 bug 的触发方法。
因为之后要对战 boss,因此要收集足够的体力,但是如果打过 boss 并且剩了体力就无法触发后续剧
情,所以要求收集体力恰好为 X。Kanade 可以随心所欲地触发或不触发任意补给点的任何 bug,请问
她有多少种方式能够在全部走完这 n 个补给点后收集到 X体力。
输入
从 building.in 中读入以下内容:
第一行两个非负整数n,X ,表示补给点个数和需要收集的体力数;
第二行 n 个非负整数 ai,第 i 个整数表示在不触发 bug 的情况下补给点 i 提供的体力。
输出
输出到 building.out。
输出一行一个整数,表示收集到 X 体力的方法数。
对于 60% 的数据,1<=n<=10 ;
对于 100% 的数据,1<=n<=25,1<=X,ai<=1e13 。
Solution
折半搜索
1 #include<cstdio> 2 #include<algorithm> 3 #include<map> 4 using namespace std; 5 const int N=30; 6 int n; long long X,ans,a[N],f[N]; 7 inline int cal(long long x) 8 {int cnt=0; 9 while(x) x=(x&(x-1)),cnt++; 10 return cnt; 11 } 12 map<long long,long long> s; 13 void dfs(int i,long long x) 14 {if(x>X) return; 15 16 if(i>n/2) {s[x]++; return ;} 17 dfs(i+1,x); dfs(i+1,x+a[i]); dfs(i+1,x+f[i]); 18 } 19 void hehe(int i,long long x) 20 {if(x>X) return; 21 if(i>n) {ans=ans+s[X-x];return ;} 22 hehe(i+1,x); hehe(i+1,x+a[i]); hehe(i+1,x+f[i]); 23 } 24 int main() 25 { 26 scanf("%d%lld",&n,&X); 27 for(int i=1;i<=n;i++) {scanf("%lld",&a[i]); f[i]=(1ll<<cal(a[i])); } 28 dfs(1,0); hehe(n/2+1,0); 29 printf("%lld",ans); 30 return 0; 31 }
原文地址:https://www.cnblogs.com/YuXiaoze/p/11839524.html
时间: 2024-11-06 11:54:55