J.Easy Integration
公式題,沃利斯積分:\(\int_{0}^{1}{(x-x^2)^n}dx=\frac{(n!)^2}{(2n+1)!}\)
一直按照分部積分公式:\(\int{u(x)v'(x)dx}=u(x)v(x)-\int{u'(x)v(x)dx}\)
推導:
\(\int_{0}^{1}{(x-x^2)^n}dx\)
\(=\frac{1}{n+1}\int_{0}^{1}{[x^{n+1}]'\ (1-x)^n dx}\)
\(=\frac{1}{n+1}(x^{n+1}(1-x)^n|_0^1-\int_{0}^{1}{x^{n+1}[(1-x)^n]'}dx)\)
\(=\frac{n}{n+1}\int_{0}^{1}{x^{n+1}(1-x)^{n-1}}dx\)
以此類推,可得:
\(\frac{n*(n-1)*...*1*\int_{0}^{1}{x^{2n}}}{(n+1)*(n+2)*...*(2n)}\)
\(=\frac{n!}{(n+1)*...*(2n+1)}\)
\(=\frac{(n!)^2}{(2n+1)!}\)
代碼:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int N=1e6+6;
const int maxn=2e6+1;
ll f[N<<1],inv[N<<1];
ll power(ll a,ll b)
{
ll res=1;
while(b)
{
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
void init()
{
f[0]=1;//階乘
for(int i=1;i<=maxn;i++)
f[i]=f[i-1]*i%mod;
for(int i=0;i<=maxn;i++)//1!~(2n+1)!逆元
inv[i]=power(f[i],mod-2);
}
int main()
{
init();
int n;
while(scanf("%d",&n)!=EOF)
{
ll ans=f[n]*f[n]%mod*inv[2*n+1]%mod;
printf("%lld\n",ans);
}
return 0;
}
I.1 or 2
解1:
拆點,求最大匹配。
但這樣寫,應該有問題的。不能保證上次從點 \(u\) 取了和 \(v\) 之間的邊,下次從 \(v\) 就會取和 \(u\) 之間的邊。
比如下面的圖就就有問題
應該輸出 \(No\),但輸出了 \(Yes\)。
代碼1:
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=110;
const int inf=0x3f3f3f3f;
struct node
{
int to,val,rev;//邊的終點,邊的容量,方向邊的索引
};
vector<node>pic[N<<1];
queue<int>que;
int layer[N<<1],iter[N<<1];//iter[]數組用於當前弧優化
int vn,s,t;
bool bfs()
{
for(int i=0;i<=vn;i++)
layer[i]=-1;
while(!que.empty())
que.pop();
layer[s]=0;
que.push(s);
while(!que.empty())
{
int a=que.front();
que.pop();
for(int i=0;i<pic[a].size();i++)
{
node b=pic[a][i];
if(layer[b.to]<0&&b.val>0)//layer[]相對於標記
{
layer[b.to]=layer[a]+1;
que.push(b.to);
if(b.to==t)//不用把所有的點都分層,只要分到匯點就行
return true;
}
}
}
return false;
}
int dfs(int a,int c)//
{
if(a==t)
return c;
for(int &i=iter[a];i<pic[a].size();i++)//當前弧優化,已經用過非邊不再遍歷,引用
{
node &e=pic[a][i];//引用,后面可以直接修改數據
if(e.val>0&&layer[e.to]>layer[a])//只走后面的層次的點
{
int d=dfs(e.to,min(c,e.val));//每次找到一條增廣路后,一直回溯到起點,並在此過程中確定路上的最小流量
if(d>0)
{
e.val-=d;
pic[e.to][e.rev].val+=d;//改變時要對原來的信息修改
return d;//返回該條增廣路的最大流
}
}
}
return 0;//
}
int dinic()
{
int max_flow=0;
while(bfs())
{
int f=0;
memset(iter,0,sizeof(iter));
while((f=dfs(s,inf))>0)
max_flow+=f;
}
return max_flow;
//printf("%d\n",max_flow);
}
void add(int u,int v,int w)
{
pic[u].pb({v,w,pic[v].size()});
pic[v].pb({u,0,pic[u].size()-1});
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
int d=0,tol=0;
vn=2*n+1;
s=0,t=vn;
for(int i=0;i<=vn;i++)
pic[i].clear();
for(int i=1;i<=n;i++)
{
scanf("%d",&d);
tol+=d;
add(0,i,d);
add(i+n,vn,d);
}
int u,v;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
add(u,v+n,1);
add(v,u+n,1);
}
int ans=dinic();//cout<<"ans="<<ans<<endl;cout<<"tol="<<tol<<endl;
if(ans==tol) printf("Yes\n");
else printf("No\n");
}
return 0;
}
代碼2:
#include <bits/stdc++.h>
#define pb push_back
using namespace std;
typedef pair<int,int>pii;
const int N=55;
int d[N],a[N];
vector<pii>pic[N];
bool vis[N<<1];
int n,m;
bool cmp(int x,int y)
{
return pic[x].size()<pic[y].size();
}
bool dfs(int k)
{
if(k>n) return 1;
if(d[a[k]]==0) return dfs(k+1);//該電的度已滿足,找下一個點
for(int i=0;i<pic[a[k]].size();i++)
{
int u=pic[a[k]][i].first;
int e=pic[a[k]][i].second;
if(vis[e]||d[u]==0) continue;//邊走過或者該點的度已經滿足
d[a[k]]--,d[u]--,vis[e]=1;
bool f=dfs(k);
if(f) return 1;
vis[e]=0,d[a[k]]++,d[u]++;
}
return 0;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(vis,false,sizeof(vis));
for(int i=1;i<=n;i++)
{
scanf("%d",&d[i]);
a[i]=i;
pic[i].clear();
}
int u,v;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
pic[u].pb(make_pair(v,i));
pic[v].pb(make_pair(u,i));
}
sort(a+1,a+1+n,cmp);//把點按度排序
if(dfs(1)) printf("Yes\n");
else printf("No\n");
}
return 0;
}