CF388 D

題意:
一個自然數集合S ,如果對於所有aSbS 都有(a xor b)S ,則稱S是perfect set。給出n,問有多少個perfect set元素都小於等於n。
n<=10^9

#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<iostream>
#define N 35
#define mmod 1000000007
#define LL long long
using namespace std;
int n,a[N],len,f[N][N][2],ans;
void upd(int &x,int y)
{
    x=(x+y)%mmod;
}
void dp()
{
    f[1][0][1]=f[1][1][0]=1;
    for(int i=1;i<len;i++)
        for(int j=0;j<=i;j++)
            for(int o=0;o<=1;o++)
            {
                if(f[i][j][o]==0) continue;
                if(a[i+1]==1 || o==1) 
                    upd(f[i+1][j+1][o],f[i][j][o]);
                if(o) upd(f[i+1][j][o],(LL)f[i][j][o]*(1ll<<j)%mmod);
                else
                {
                    upd(f[i+1][j][0],(LL)f[i][j][0]*(1ll<<(j-1))%mmod);
                    if(a[i+1]) upd(f[i+1][j][1],(LL)f[i][j][0]*(1ll<<(j-1))%mmod);
                }
            }
}
int main()
{
    scanf("%d",&n);
    if(n==0) {printf("1\n");return 0;}
    int t=n;
    while(t) {a[++len]=t%2;t/=2;}
    for(int i=1;i<=len/2;i++) swap(a[i],a[len-i+1]);
    dp();
    for(int i=0;i<=len;i++)
        for(int j=0;j<=1;j++)
            upd(ans,f[len][i][j]);
    printf("%d\n",ans);
    return 0;
}

題解:
O__O
每個perfect set都可以找出一組基是吧。。
用一種奧妙重重的消元方式能使不同的perfect set消出不同且唯一的基(腦補一下吧)。。
於是我們dp那組線性基。。
用心感受一下吧。。

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