D. Dreamoon Likes Sequences——(組合數學)

題意:

約束條件
1:數組a的長度>=1
2:1<=a1<a2<an<=d,保證數組a是嚴格的遞增
3:b1<b2<bn,保證數組b是嚴格的遞增
4:bi=bi-1 xor ai,其實bi就是前綴異或

問題:求數組的a的方案數%m

解析

定義h(x)爲x的bit最高位:
例如:h(1)=0,h(2)=1,h(3)=1.h(4)=2
通過2,3,4條件可以知道:h(ai)<h(ai+1)
這裏保證了數組b嚴格遞增

因爲ai-1<ai<ai+1
如果h(ai-1)<h(ai)==h(ai+1)
後果bi-1<bi>bi+1

簡化:2,3最多選一個,4 5 6 7最多選一個
集合1:1
集合2:2 3
集合3:4 5 6 7
集合…
然後就是dp算各種情況方案數求和

題目鏈接

//#pragma GCC optimize(2)
#include<bits/stdc++.h>
//typedef long long ll;
#define ull       unsigned long long
#define int       long long
#define F           first
#define S           second
#define endl        "\n"//<<flush
#define eps         1e-6
#define base        131
#define lowbit(x)   (x&(-x))
#define PI          acos(-1.0)
#define inf         0x3f3f3f3f
#define MAXN        0x7fffffff
#define INF         0x3f3f3f3f3f3f3f3f
#define pa          pair<int,int>
#define ferma(a,b)  pow(a,b-2)
#define pb          push_back
#define all(x)      x.begin(),x.end()
#define memset(a,b) memset(a,b,sizeof(a));
#define IOS         ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
void file()
{
#ifdef ONLINE_JUDGE
#else
    freopen("D:/LSNU/codeforces/duipai/data.txt","r",stdin);
    //  freopen("D:/LSNU/codeforces/duipai/AC.txt","w",stdout);
#endif
}
int dp[40];
signed main()
{
    IOS;
    // file();
    int t;
    cin>>t;
    while(t--)
    {
        memset(dp,0);
        int d,m;
        cin>>d>>m;
        vector<int>h;
        int cnt=0;
        for(int i=0;d;i++)
        {
            int l=1<<i;
            int r=min((1ll<<i+1)-1,d);
            h.pb(r-l+1);
            cnt++;
            if(r==d)
                break;
        }
        int ans=0;
        dp[0]=1;
        for(int i=1;i<=cnt;i++)
        {
            for(int j=i;j>=1;j--)
            {
                int num=dp[j-1]*h[i-1]%m;
                dp[j]=(dp[j]+num)%m;
                ans=(ans+num)%m;

            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章