JZOJ5765 相互再歸的鵝媽媽

2021-08-22 10:32:54 字數 1647 閱讀 1543

給出乙個01串,代表乙個二進位制數r,求包含n個非負整數、且每個整數的二進位制小於r的集合個數。

先考慮有序的,可重集怎麼求,最後再除以n!。設gi

g

i表示人數為

i i

允許出現相同的滿足條件的集合數,對於乙個人的二進位制位,我們在乙個r是1的位置填上0,這以後的數字都可以任意填,且對於其他人的無論怎麼填,這個人有唯一一種填法可以使之成立。

對於奇數個人,只能在最高位就填0來保證,所以直接計算即可,而對於偶數個人,列舉在哪一位開始填0,列舉有多少對1,計數一下(含糊,留坑)

假裝我們求出了g,我們可以列舉n(

n−1)

/2' role="presentation">n(n

−1)/

2n(n

−1)/

2中關係(及選相同的數)的出現情況來容斥,這樣會把原來的人歸為幾個塊,塊中人選擇的數相同,對於大小為偶數的塊,無論它們填什麼數異或和都為0,對於奇數的塊就當成乙個人來處理,複雜度勉強能過。

#include

#include

#include

#include

#define fo(i,j,k) for(int i=j;i<=k;++i)

#define fd(i,j,k) for(int i=j;i>=k;--i)

#define mem(a) memset(a,0,sizeof(a))

using namespace std;

typedef long long ll;

const int n=8,m=5e4+10,mo=1e9+7;

char s[m];

int a[m*100];

ll c[n][n],vl[m*100],g[n],z[m*n

*100];

ll jc[n];

void add(ll &x,ll y)

ll pow(ll x,int

y)struct nodeb[25];

int n,tot=0;

int d[25],f[n],sz[n];

bool bz[n];

ll ans=0;

int find(int

x)void dfs(int

x,int t,int z)

fo(i,1,n) bz[find(i)]=1;

int cn1=0,cn2=0;

fo(i,1,n) if(bz[i]) sz[i]&1?cn1++:cn2++;

ans=(ans+g[cn1]*pow(vl[1],cn2)%mo

*z+mo)%mo;

return;

}dfs(x+1,t,z);

d[t+1]=x,dfs(x+1,t+1,-z);

}int main()

g[0]=1;

fo(i,1,n)

}fo(i,1,n-1)

fo(j,i+1,n) b[++tot].x=i,b[tot].y=j;

dfs(1,0,1);

jc[0]=1;

fo(i,1,n) jc[i]=jc[i-1]*i

%mo;

printf("%lld",ans*pow(jc[n],mo-2)%mo);

}

uoj576 服務排程

先考慮乙個子問題 僅有乙個詢問且無修改 對每一種顏色的貢獻分類討論,結論 最遠的點一定這些點集中 任意一組 最遠點對中的兩個點 選擇較遠的乙個 證明 設 dis x,y 為 x 到 y 的距離,deep 表示以 k 為根時 x 的深度 假設這個點集中最遠點為 x,y 而最深的點為 z 且 deep ...

Leetcode 576 出界的路徑數

給定乙個 m n 的網格和乙個球。球的起始座標為 i,j 你可以將球移到相鄰的單元格內,或者往上 下 左 右四個方向上移動使球穿過網格邊界。但是,你最多可以移動 n 次。找出可以將球移出邊界的路徑數量。答案可能非常大,返回 結果 mod 109 7 的值。示例 1 輸入 m 2,n 2,n 2,i ...

leetcode576 出界的路徑數

題目 給定乙個 m n 的網格和乙個球。球的起始座標為 i,j 你可以將球移到相鄰的單元格內,或者往上 下 左 右四個方向上移動使球穿過網格邊界。但是,你最多可以移動 n 次。找出可以將球移出邊界的路徑數量。答案可能非常大,返回 結果 mod 10 9 7 的值。一開始看題,以為類似機械人路徑問題,...