給出乙個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 的值。一開始看題,以為類似機械人路徑問題,...