【每日一题】1月29日题目 和与或
生活随笔
收集整理的這篇文章主要介紹了
【每日一题】1月29日题目 和与或
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:
給你一個數組R,包含N個元素,求有多少滿足條件的序列A使得
0 ≤ A[i] ≤ R [ i ]
A[0]+A[1]+…+A[N?1] =A[0] | ]A[1]… | A [ N ? 1 ]
輸出答案對1e9+9取模
題解:
參考博客
數位dp問題
如果和等于或的話,說明兩種情況:
說明要滿足等式,每一位數的二進制只能出現在這個n個數中的某一位上
我們簡化問題,對于(a,b),如果a + b= a | b且a<=r0&&b<=r1
設dp[len][limit1][limit2]表示枚舉到二進制第len位,a是否限制,b是否限制,limit1和limit2的值為0或1,
這樣我們只需要暴力考慮當前位二進制填0還是1,并考慮是填在a還是b
現在將問題擴展,對于(a,b,c,…),根據題目n最多10,那我們開個11維的數組就可以了dp[len][2][2]…[2],但是我們注意到從第二位到最后一位都只用來表示0和1,那么我們將這些壓縮,用二進制壓縮,這樣就成二維數組了dp[len][x].x的二進制下表示每個數卡不卡上界
代碼:
代碼里有加注釋
#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; }總結
以上是生活随笔為你收集整理的【每日一题】1月29日题目 和与或的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网页type怎么修改()
- 下一篇: 备案施工图去哪里查(备案施工)