51nod 1776 路徑計數

2022-05-08 03:21:12 字數 1661 閱讀 6502

我們先把前兩種數給排好,排好之後會有\(a + b + 1\)個空隙可以填數,我們計算有\(k\)個空隙兩端都是相同字母的方案數

可以用列舉把第二種數分成幾段插進去來算,設這個方案數為\(f[k]\)

然後對於一種有\(k\)個空隙的方案數,列舉剩下的\(a + b + 1 - k\)個空隙填了\(h\)個

然後計算把\(c\)和\(d\)分成\(k + h\)段的方案數就好了,記為\(g[k + h]\)

那麼如何計算\(g[i]\)呢

一段要麼是偶數,\(c\)和\(d\)個數相等,一段要麼是奇數,\(c\)多或者\(d\)多

對於乙個\(i\),強制認為\(c\)多的有\(j\)個,那麼可以求出\(d\)多的是\(k\)個,剩下的必須兩兩配對,把剩下的\(i - j - k\),填成\(dc\)或者\(cd\),有兩種方案

然後剩下的\(cd\)的對子,扔到\(i\)個區間中排列方法是唯一的,只要計算切成\(i\)段每段可以為空的方案數是多少就行了,是個組合數

#include #define fi first

#define se second

#define pii pair#define mp make_pair

#define pb push_back

#define space putchar(' ')

#define enter putchar('\n')

#define eps 1e-10

#define ba 47

#define maxn 1000005

//#define ivorysi

using namespace std;

typedef long long int64;

typedef unsigned int u32;

typedef double db;

templatevoid read(t &res)

while(c >= '0' && c <= '9')

res *= f;

}templatevoid out(t x)

if(x >= 10)

putchar('0' + x % 10);

}const int mod = 998244353;

int fac[10005],invfac[10005],f[5005],g[5005],pw[5005];

int a[5],n;

int inc(int a,int b)

int mul(int a,int b)

void update(int &x,int y)

int fpow(int x,int c)

return res;

}int c(int n,int m)

int main()

memset(f,0,sizeof(f));

memset(g,0,sizeof(g));

for(int i = 1 ; i <= a[2] + a[3] ; ++i)

}for(int i = 1 ; i <= a[1] ; ++i)

}int ans = 0;

for(int i = 0 ; i <= a[0] + a[1] ; ++i)

}out(ans);enter;

}}

51nod 1610 路徑計數

原題連線 考慮不同權重為 d 的倍數的邊組成的圖.f d 為此圖中。路徑總數量。由於m 50000 明顯會出現重邊。建議限制邊的數量或者使用鄰接矩陣存圖。矩陣更為方便。由於最初沒有考邊過多。使用了鍊錶 拓撲排序。量較大。include include include include define m...

51Nod1967 路徑定向

給出乙個有向圖,要求給每條邊重定向,使得定向後出度等於入度的點最多,輸出答案和任意一種方案 input 第一行兩個正整數n,m,表示1 n號點與m條邊 接下來m行,每行兩個正整數xi,yi,表示存在一條有向邊從xi指向yi n 10 5,m 3 10 5,xi,yi n output 第一行乙個整數...

51NOD 1967 路徑定向

給出乙個有向圖,要求給每條邊重定向,使得定向後出度等於入度的點最多,輸出答案和任意一種方案.n 10 5,m 3 10 5,xi,yi n 考慮先當每條邊雙向。如果這個圖的所有點的度都是偶數,那麼尤拉路徑跑一下就行了 考慮度為奇數的點 連線所有度為奇數的點,使其成為偶數點,顯然不會影響正確性 留個坑...