2020牛客多校第一场By Rynar
A.B-Suffix Array
B.Infinite Tree
C.Domino
D.Quadratic Form
E.Counting Spanning Trees
F.Infinite String Comparision
Periodicity Lemma:对于S周期p,q,p+q-gcd(p,q)<=|S|,则|p-q|,gcd(p,q)也是周期
可得:>=a+b-gcd(a,b)就可以比较大小
证明Periodicity Lemma:
先证引理:对于S周期p,q,gcd(p,q)=1,p+q-1<=|S|,则gcd(p,q)也是周期
令p>q,p=kq+t,此处s下标从1开始p+q-1结束
i==p时,s[i]=s[t]=s[t+p](t+p=kq+t+t<p+q-1=kq+q+t)=s[2*t%p]=...
因为gcd(p,q)==1,必然搜到所有点
即s[1]=s[2]=...=s[p+q-1],则gcd(p,q)=1也为S的周期
因此引理得证
接下去证明,不妨令|S|=p+q-gcd(p,q)
把gcd(p,q)整段当成一个字母,可由上面引理得此时gcd(p,q)也为周期
当|S|>=p+q-gcd(p,q),易得gcd(p,q)也为周期
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
char a[N],b[N];
int gcd(int x,int y){
return x%y?gcd(y,x%y):y;
}
signed main(){
while (scanf("%s%s",&a,&b)==2){
int l1=strlen(a),l2=strlen(b);
int g=l1+l2-gcd(l1,l2);
for (int i=l1;i<g;i++)a[i]=a[i-l1];
for (int i=l2;i<g;i++)b[i]=b[i-l2];
a[g]=b[g]='\0';
int p=strcmp(a,b);
if (p==0)puts("=");
else if (p>0)puts(">");
else puts("<");
}
return 0;
}
G.BaXianGuoHai, GeXianShenTong
H.Minimum-cost Flow
题意:每条边的cost已经确定,所有边的流量相等却不确定,给出q(<1e6)组流量情况,用u/v(>1)表示,输出流出1流量所需要的cost a/b,若不能输出1流量,则输出NaN
思路:先增广费用流求出所有的增广路,并做前缀和,面对询问,直接利用前缀和位置输出cost or NaN
const int N=1001+10;
int n,m,k;
int Cost=0,Flow=0;
int vis[N],dis[N],head[N];
int step;
struct node{
int to,cap,cost,n;
}e[N<<1];
void add(int x,int y,int v,int c){
e[step].to=y;
e[step].cap=v;
e[step].cost=c;
e[step].n=head[x];
head[x]=step++;
}
bool spfa(int s,int t){
for(int i=0;i<=n;i++) vis[i]=0,dis[i]=inf;//要改
deque<int>q;
q.push_back(t);
dis[t]=0;
vis[t]=1;
while(!q.empty()){
int u=q.front();
q.pop_front();
for(int i=head[u];~i;i=e[i].n){
int v=e[i].to;
if(e[i^1].cap&&dis[v]>dis[u]+e[i^1].cost){
dis[v]=dis[u]+e[i^1].cost;
if(!vis[v]){
vis[v]=1;
if(!q.empty()&&dis[v]<dis[q.front()]){//SLF优化
q.push_front(v);
}
else q.push_back(v);
}
}
}
vis[u]=0;
}
return dis[s]<inf;
}
int dfs(int s,int t,int flow){
vis[s]=1;
if(s==t||flow<=0) return flow;
int res,used=0;
for(int i=head[s];~i;i=e[i].n){
int v=e[i].to;
if(!vis[v]&&e[i].cap&&dis[s]-dis[v]==e[i].cost){
res=dfs(v,t,min(e[i].cap,flow-used));
if(res) {
e[i].cap-=res;
e[i^1].cap+=res;
Cost+=res*e[i].cost;
used+=res;
}
if(used==flow)break;
}
}
return used;
}
void zkw(int s,int t){
while(spfa(s,t)){
vis[t]=1;
while(vis[t]){
for(int i=0;i<=n;i++) vis[i]=0;//要改
Flow+=dfs(s,t,inf);
}
}
}
ll gcd (ll x,ll y){
return x%y?gcd(y,x%y):y;
}
int fl[N],co[N],sum[N];
int main(){
int s,t,T;
while (scanf("%d%d",&n,&m)==2){
step=0;
memset(head,-1,sizeof head);
rep(i,1,m){
int u,v,f;
scanf("%d%d%d",&u,&v,&f);
add(u,v,1,f);
add(v,u,0,-f);
}
add(0,1,1,0);
add(1,0,0,0);
int cnt=0;
for (int i=1;i<=101;i++){//增广所有的路
Cost=0,Flow=0;
e[step-1].cap=0;
e[step-2].cap=1;
zkw(0,n);
if (Flow==0&&Cost==0){
cnt=i-1;
break;
}
fl[i]=Flow;co[i]=Cost;
}
sum[0]=0;
for (int i=1;i<=cnt;i++)sum[i]=sum[i-1]+co[i];
scanf("%d",&T);
while (T--){
scanf("%d%d",&s,&t);
if (s==0){
printf("NaN\n");
continue;
}
ll cost=0,flow=t;
if (t/s>cnt||(t/s==cnt&&t%s)){
printf("NaN\n");
}
else{
cost=1ll*sum[t/s]*s+(t-t/s*s)*co[t/s+1];
ll g=gcd(cost,flow);
printf("%lld/%lld\n",cost/g,flow/g);
}
}
}
return 0;
}
I.1 or 2
题意:n个点,m条边,取其中一定的边满足每个点的度都是的d[i],问能否满足
思路:一般图匹配,带花树算法,建图如下,每个点的点数为度数的个数

const int N=2333;
int n,m;
int cnt,match[N];//点数INIT
int fa[N];
vector<int>g[N];//INIT
int tp[N],pre[N];
queue<int>q;
int tim=0,tic[N];
void add(int u,int v){g[u].pb(v);g[v].pb(u);}
int ff(int x){if(x == fa[x]) return x; return fa[x]=ff(fa[x]);}
int lca(int x, int y){
tim++;x=ff(x);y=ff(y);
while(tic[x]!=tim){
tic[x]=tim;
x=ff(pre[match[x]]);
if(y)swap(x, y);
}
return x;
}
void go(int u,int v,int p){
while(ff(u)!=p){
pre[u]=v;v=match[u];
if(tp[v]==2) tp[v]=1,q.push(v);//
if(ff(u)==u) fa[u]=p;
if(ff(v)==v) fa[v]=p;
u=pre[v];
}
}
bool aug(int s){
while(q.size()) q.pop(); q.push(s);
fors(i, 0, N+1) fa[i] = i, pre[i] = tp[i] = 0;
tp[s] = 1;
while(q.size()){
int u = q.front(); q.pop();
for(int v: g[u]){
if(tp[v] == 2||ff(u)==ff(v)) continue;
if(!tp[v]){
tp[v] = 2; pre[v] = u;
if(!match[v]){//找到增广点,一路返回修改
int now = v, tmp;
while(now){
tmp = match[pre[now]];
match[pre[now]] = now; match[now] = pre[now];
now = tmp;
}
return true;
}
tp[match[v]] = 1; q.push(match[v]);
}else if(tp[v] == 1){
int p = lca(u, v);
go(u,v,p); go(v, u, p);
}
}
}return false;
}
int d[N],sumd;
vector<int>to[N];
void init(){
sumd=0;
cnt=0;
for (int i=1;i<=n;i++)to[i].clear();
for (int i=1;i<=n;i++){
scanf("%d",&d[i]), sumd+=d[i];
for (int j=1;j<=d[i];j++) to[i].pb(++cnt),g[cnt].clear();
}
for (int i=1;i<=m;i++){
int u,v;
scanf("%d%d", &u, &v);
++cnt; g[cnt].clear();
for(int id: to[u]) add(id,cnt);
++cnt; g[cnt].clear(); add(cnt,cnt-1);
for(int id: to[v]) add(id,cnt);
}
}
bool solve(){
int ans = 0;
for (int i=1;i<=cnt;i++) match[i]=0;
for (int i=1;i<=cnt;i++) ans+=(!match[i] && aug(i));
return ans*2==cnt;
}
int main(){
while(scanf("%d%d",&n,&m)==2){
init();
if(solve())puts("Yes");
else puts("No");
}
}
J.Easy Integration
\[\int_0^1 {(x-x^2)^n}\,{\rm d}x=\int_0^1 {x^n*(1-x)^n}\,{\rm d}x=(\frac{1}{n+1}{x^{n+1}*(1-x)^n}){|^0_1}+\frac{n}{n+1}\int_0^1 {x^{n+1}*(1-x)^{n-1}}\,{\rm d}x\\
=\frac{n}{n+1}\int_0^1 {x^{n+1}*(1-x)^{n-1}}\,{\rm d}x =\frac{n!}{(n+1)*(n+2)*...*(2*n)}\int_0^1{x^{2*n}}\,{\rm d}x=\frac{n!*n!}{(2*n+1)!}\]
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e6+10;
const int mod=998244353;
int x[N];
int qpow(ll x,int y){
int ans=1;
while (y){
if (y&1)ans=ans*x%mod;
x=x*x%mod;y>>=1;
}
return ans;
}
signed main(){
x[1]=1;
for (ll i=2;i<N;i++){
x[i]=x[i-1]*i%mod;
}
int n;
while (scanf("%d",&n)!=EOF){
printf("%d\n",1ll*x[n]*x[n]%mod*qpow(x[2*n+1],mod-2)%mod);
}
return 0;
}
禁止类似码农教程的网站爬取,抄袭博客内容。
https://www.cnblogs.com/rair/

浙公网安备 33010602011771号