题意:
有一个长度为N的数组R,求有多少满足条件的序列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的N个数和与或结果相等,所以每一位最多存在于这n个数中的其中一个数中。所以可以从高位到低位枚举结果,用数位dp和状压思想优化。
dp[i][j]表示从第0位枚举到i位并且此时状态位j时满足条件的方案数。
(j在第o位为1表示第o个数在第i位取数一定小于等于该数在第i位的值,j在第o位为0表示第o个数在第i位可以随便取值,保证枚举时A[i]<=R[i])。

代码:

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const ll inf=1e9+9;

ll n, a[15], dp[65][2005];

ll dfs(ll pos,ll s)
{
    if(pos<0)
    {
        return 1LL;
    }
    if(dp[pos][s]!=-1)
    {
        return dp[pos][s];
    }
    ll ans=0, s1=s;
    for(int i=0;i<n;i++)
    {
        if(((s>>i)&1)&&(!((a[i]>>pos)&1)))
        {
            ;
        }
        else if(((s>>i)&1))
        {
            s1=s1-(1LL<<i);
        }
    }
    ans=(ans+dfs(pos-1,s1))%inf;
    for(int i=0;i<n;i++)
    {
        if((!((s>>i)&1))||(((s>>i)&1)&&((a[i]>>pos)&1)))
        {
            if(((s>>i)&1)&&(((a[i]>>pos)&1)))
            {
                ans=(ans+dfs(pos-1,s1|(1LL<<i)))%inf;
            }
            else
            {
                ans=(ans+dfs(pos-1,s1))%inf;
            }
        }
    }
    if(dp[pos][s]==-1)
    {
        dp[pos][s]=ans;
    }
    return ans;
}

int main()
{
    memset(dp,-1,sizeof(dp));
    scanf("%lld",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%lld",&a[i]);
    }
    cout << dfs(60,(1LL<<n)-1) << endl;
    return 0;
}