(拿来监督自己补补题)
题目描述
给定一个 n n n,求 ∫ 0 1 ( x − x 2 ) n d x \int_{0}^{1} (x-x^2)^n dx ∫01(x−x2)ndx 约分后的答案。
思路
在不知道公式的情况下,这是一个规律题。可以通过对前几项做计算可以发现,以 1 , 2 , 3 1,2,3 1,2,3为例
n = 1 , r e s = 1 2 ∗ 3 n = 1,res=\frac{1}{2*3} n=1,res=2∗31等价于 1 2 ∗ 3 \frac{1}{2*3} 2∗31
n = 2 , r e s = 2 3 ∗ 4 ∗ 5 n=2,res=\frac{2}{3*4*5} n=2,res=3∗4∗52等价于 1 ∗ 2 3 ∗ 4 ∗ 5 \frac{1*2}{3*4*5} 3∗4∗51∗2
n = 3 , r e s = 6 4 ∗ 5 ∗ 6 ∗ 7 n=3,res=\frac{6}{4*5*6*7} n=3,res=4∗5∗6∗76等价于 1 ∗ 2 ∗ 3 4 ∗ 5 ∗ 6 ∗ 7 \frac{1*2*3}{4*5*6*7} 4∗5∗6∗71∗2∗3
所以可以很快得出规律公式
( n ! ) 2 ( 2 n + 1 ) ! \frac{(n!)^2}{(2n+1)!} (2n+1)!(n!)2
正确证明
已知有贝塔函数 B ( P , Q ) = ∫ 0 1 x P − 1 ( 1 − x ) Q − 1 d x B(P,Q)=\int_{0}^{1} x^{P-1}(1-x)^{Q-1} dx B(P,Q)=∫01xP−1(1−x)Q−1dx
贝塔函数与伽马函数的关系
B ( P , Q ) = P + Q P Q C P + Q P = 1 Q C P + Q − 1 P − 1 B(P,Q)=\frac{P+Q}{PQC_{P+Q}^P}=\frac{1}{QC_{P+Q-1}^{P-1}} B(P,Q)=PQCP+QPP+Q=QCP+Q−1P−11
文献资料链接
所以原公式 ∫ 0 1 ( x − x 2 ) n d x = ∫ 0 1 x n ( 1 − x ) n d x = 1 ( n + 1 ) C 2 n + 1 n \int_{0}^{1} (x-x^2)^n dx=\int_{0}^{1} x^n(1-x)^n dx=\frac{1}{{(n+1)}C_{2n+1}^{n}} ∫01(x−x2)ndx=∫01xn(1−x)ndx=(n+1)C2n+1n1
代码
#include
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int p = 998244353;
const int N = 2e6 + 10;
LL fac[N], infac[N];
LL n;
LL kpow(LL a, LL n) {
LL res = 1;
while(n) {
if(n & 1) res = (res * a) % p;
n >>= 1;
a = (a * a) % p;
}
return res;
}
void init() {
fac[0] = infac[0] = 1;
for(int i = 1; i < N; i++) {
fac[i] = (fac[i - 1] * i) % p;
infac[i] = (infac[i - 1] * kpow(i, p - 2)) % p;
}
}
LL C(int a, int b) {
return fac[a] * infac[b] % p * infac[a - b] % p;
}
void solve() {
printf("%lld\n", kpow(n + 1, p - 2) * kpow(C(2 * n + 1, n), p - 2) % p);
}
int main() {
init();
// freopen("in.txt", "r", stdin);
//int t; cin >> t; while(t--)
while(~scanf("%d",&n))
solve();
return 0;
}
题目描述
给定两个字符串a,b。比较无限个字符串a拼接和无限个字符串b拼接的大小。
思路
看到一个很nb的做法,仔细想了想,发现这个思路tql。
比较a + b和 b + a的大小。
字符串a,b长度相等就没什么可比性了。
这里假设strlen(a) < strlen(b)
如果前 len(a) 个字符有大小不相等的,那一定输出大于或小于了。但如果b字符串前len(a)个字母与a相等 ,就相当于将b字符串第len(a)+1位与字符串a的第1位相比较,因为b字符串前len(a)个字符与字符串a相同,就等价于b字符串的第len(a)+1位与其第一位比较是否相同。b字符串后面接a也是相同道理。自己的思维还是太拉跨了
代码
#include
using namespace std;
int main() {
// freopen("in.txt", "r", stdin);
string a, b;
while(cin >> a >> b) {
string A = a + b;
string B = b + a;
if(A > B) puts(">");
else if(A == B) puts("=");
else puts("<");
}
return 0;
}
题目描述
给定一个 n n n个点, m m m条边的无向图,是否存在一个子图,使其每个点的度数为 d i d_i di
进阶版题目 hdu3551
思路
问是否存在一个子图,考虑删边。每删除一条边会将两个点的度减一。将每个点的度拆分成一个个点。然后对图进行拆分,一条边所对应的点拆分成两个点 u u u 和 v v v ,将他们所对应的度数的点与其对应的点连边。
比赛的时候想到过二分图最大匹配,将度数拆成的点与边拆的两个点一一匹配,若想要成立,边拆成的点一定要大于等于点的度数拆成的点。如果只进行二分图匹配,那么边所产生的两个点 u u u 和 v v v 可能并不能完全匹配二次。
所以在匹配完度数的拆点和点之后,要去看剩下没有被完全占用的边是否一次都没有被占用,等价于剩下没有被占用的边的两个点也都需要两两匹配,所以需要一般图匹配,也就是带花树算法。
代码
带花树算法模板抄kuangbin的,只有 C r e a t G r a p h ( ) CreatGraph() CreatGraph()函数和 P r i n t M a t c h ( ) PrintMatch() PrintMatch()函数改了改
#include
using namespace std;
typedef pair<int, int> PII;
typedef long long LL;
const int N = 110, M = 410;
vector<int> e[N];
int n, m;
int d[N];
int idx;
PII edge[N];
vector<int> du[N];
bool Graph[M][M];
int Match[M];
bool InQueue[M], InPath[M], InBlossom[M];
int Head, Tail;
int Queue[M];
int Start, Finish;
int NewBase;
int Father[M], Base[M];
int Count;
void init() {
for(int i = 1; i <= n; i++) {
e[i].clear();
du[i].clear();
}
memset(d, 0, sizeof d);
memset(edge, 0, sizeof edge);
memset(Graph, 0, sizeof Graph);
memset(Match, 0, sizeof Match);
memset(InQueue, 0, sizeof InQueue);
memset(InPath, 0, sizeof InPath);
memset(InBlossom, 0, sizeof InBlossom);
memset(Queue, 0, sizeof Queue);
memset(Father, 0, sizeof Father);
memset(Base, 0, sizeof Base);
Count = Start = Finish = NewBase = Head = Tail = idx = 0;
}
void CreatGraph() {
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= d[i]; j++) {
du[i].push_back(++idx);
}
}
for(int i = 1; i <= m; i++) {
int u = edge[i].first, v = edge[i].second;
int a = ++idx, b = ++idx;
Graph[a][b] = Graph[b][a] = 1;
for(int j = 0; j < du[u].size(); j++) {
int x = du[u][j];
Graph[a][x] = Graph[x][a] = 1;
}
for(int j = 0; j < du[v].size(); j++) {
int x = du[v][j];
Graph[b][x] = Graph[x][b] = 1;
}
}
}
void Push(int u) {
Queue[Tail] = u;
Tail++;
InQueue[u] = true;
}
int Pop() {
int res = Queue[Head];
Head++;
return res;
}
int FindCommonAncestor(int u, int v) {
memset(InPath, false, sizeof(InPath));
while(true) {
u = Base[u];
InPath[u] = true;
if(u == Start) break;
u = Father[Match[u]];
}
while(true) {
v = Base[v];
if(InPath[v]) break;
v = Father[Match[v]];
}
return v;
}
void ResetTrace(int u) {
int v;
while(Base[u] != NewBase) {
v = Match[u];
InBlossom[Base[u]] = InBlossom[Base[v]] = true;
u = Father[v];
if(Base[u] != NewBase) Father[u] = v;
}
}
void BloosomContract(int u, int v) {
NewBase = FindCommonAncestor(u, v);
memset(InBlossom, false, sizeof(InBlossom));
ResetTrace(u);
ResetTrace(v);
if(Base[u] != NewBase) Father[u] = v;
if(Base[v] != NewBase) Father[v] = u;
for(int tu = 1; tu <= idx; tu++) {
if(InBlossom[Base[tu]]) {
Base[tu] = NewBase;
if(!InQueue[tu]) Push(tu);
}
}
}
void FindAugmentingPath() {
memset(InQueue, false, sizeof(InQueue));
memset(Father, 0, sizeof Father);
for(int i = 1; i <= idx; i++) Base[i] = i;
Head = Tail = 1;
Push(Start);
Finish = 0;
while(Head < Tail) {
int u = Pop();
for(int v = 1; v <= idx; v++) {
if(Graph[u][v] && (Base[u] != Base[v]) && (Match[u] != v)) {
if((v == Start) || ((Match[v] > 0) && Father[Match[v]] > 0)) {
BloosomContract(u, v);
}
else if(Father[v] == 0) {
Father[v] = u;
if(Match[v] > 0) Push(Match[v]);
else {
Finish = v;
return;
}
}
}
}
}
}
void AugmentPath() {
int u, v, w;
u = Finish;
while(u > 0) {
v = Father[u];
w = Match[v];
Match[v] = u;
Match[u] = v;
u = w;
}
}
void Edmonds() {
memset(Match, 0, sizeof Match);
for(int u = 1; u <= idx; u++) {
if(Match[u] == 0) {
Start = u;
FindAugmentingPath();
if(Finish > 0) AugmentPath();
}
}
}
void PrintMatch() {
Count = 0;
for(int u = 1; u <= idx; u++) {
if(Match[u] > 0) Count++;
}
if(Count == idx) puts("Yes");
else puts("No");
}
void solve() {
CreatGraph();
Edmonds();
PrintMatch();
}
int main() {
freopen("in.txt", "r", stdin);
while(~scanf("%d%d", &n, &m)) {
init();
for(int i = 1; i <= n; i++) {
scanf("%d", &d[i]);
}
for(int i = 1; i <= m; i++) {
int u, v;
scanf("%d%d", &u, &v);
e[u].push_back(v);
e[v].push_back(u);
edge[i] = {u, v};
}
solve();
}
return 0;
}