我們先把前兩種數給排好,排好之後會有\(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 考慮先當每條邊雙向。如果這個圖的所有點的度都是偶數,那麼尤拉路徑跑一下就行了 考慮度為奇數的點 連線所有度為奇數的點,使其成為偶數點,顯然不會影響正確性 留個坑...