题号 NC21336
名称 和与或
戳我进入往期每日一题汇总贴~
往期每日一题二期题单
如果你在题库做题时遇到了喜欢的题目,欢迎推荐给邓老师~ 点击查看详情
欢迎给每日一题投稿,投稿需要提供牛客题库里的题目+题解 投稿有牛币奖励,可发站内信给王清楚或联系QQ 234186389
每日一题QQ群:659028468
题解
作者:喵渺淼妙的死忠粉
题目描述:你一个数组R,包含N个元素,求有多少满足条件的序列A使得0≤A[i]≤R[i].A[0]+A[1]+...+A[N-1]=A[0] or A[1]... or A[N-1]输出答案对1e9+9取模.
首先知道等式成立的条件是对于每一位分配的A[i],不可能存在2个1,也就是说最多分配一个1.然后就是介绍dp的含义了.
dp需要开两维dp[k][i],第一维是分配到了第k位,第二维是这些A[]前k-1位是不是与R[]相同,然后直接dfs即可.
冷静分析复杂度是60*(1<<10).
代码如下:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const ll N=11,M=65; const ll mod=1e9+9; ll R[N]; int n; ll dp[M][1<<N]; inline ll dfs(ll s,ll pos)//每个与前面相同情况,现在分配到了第pos位. { ll &ans=dp[pos][s]; if(pos<=0) return 1; if(ans) return ans; //先分配0. int sp=s; for(int i=0;i<n;i++) { if((s&(1<<i))&&(R[i]&(1ll<<(pos-1))))//假设这一位和R[i]的前pos-1位相同. { sp^=(1<<i); } } ans=(ans+dfs(sp,pos-1))%mod; //分配一个1. for(int i=0;i<n;i++) { if((s&(1<<i))) { if(!(R[i]&(1ll<<(pos-1)))) continue; ans=(ans+dfs(sp^(1ll<<i),pos-1))%mod; } else ans=(ans+dfs(sp,pos-1))%mod; } return ans; } int main() { scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%lld",&R[i]); } printf("%lld\n",dfs((1<<n)-1,60ll)); return 0; }
欢迎各位大佬来做题写题解,也欢迎大家踊跃在当日讨论贴中提问!
活动奖励:
在牛客博客中写出题解,并回复地址
审核通过可获得(依据题目难度和题解的内容而定)
本道题目2月5日中午12:00之前写的题解有获得牛币资格~
牛客博客开通方式
- 如何开通牛客博客:https://www.nowcoder.com/discuss/202952
- 如何使用博客搬家功能:进入博客--->设置--->底部博客搬家
- 如果你对牛客博客有任何意见或建议:牛客博客意见反馈专贴
全部评论
(7) 回帖