2019 Multi-University Training Contest 2

http://acm.hdu.edu.cn/contests/contest_show.php?cid=849

1005. Everything Is Generated In Equal Probability

考虑一个随机的排列的逆序对个数,显然对于两个数\(a,b\),他们位置是均匀排布的,也就是说有\(\frac{1}{2}\)的概率成为逆序对,并且是独立的。

所以一个长度为\(n\)的随机排列期望逆序对个数为\(\dfrac{\binom{n}{2}}{2}\)。

我们考虑\(dp\),设\(f_i\)表示长度为\(i\)随机排列扔到给出的函数里的期望输出。

那么直接照着函数转移:

\[f_i=\frac{\binom{n}{2}}{2}+\frac{1}{2^n}\sum_{j=0}^{i}\binom{i}{j}f_j
\]

暴力转移,\(O(1)\)回答就好了。

复杂度\(O(n^2+q)\)。

#include<bits/stdc++.h>
using namespace std; void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
} void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double #define pii pair<int,int >
#define vec vector<int > #define pb push_back
#define mp make_pair
#define fr first
#define sc second #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) const int maxn = 1e6+10;
const int inf = 1e9;
const lf eps = 1e-8;
const int mod = 998244353; int f[maxn],fac[maxn],ifac[maxn],n; int qpow(int a,int x) {
int res=1;
for(;x;x>>=1,a=1ll*a*a%mod) if(x&1) res=1ll*res*a%mod;
return res;
} int c(int a,int b) {return 1ll*fac[a]*ifac[b]%mod*ifac[a-b]%mod;} int main() {
fac[0]=ifac[0]=1;
for(int i=1;i<=3000;i++) fac[i]=1ll*fac[i-1]*i%mod,ifac[i]=1ll*ifac[i-1]*qpow(i,mod-2)%mod;
for(int i=2;i<=3000;i++) {
for(int j=2;j<=i-1;j++) f[i]=(f[i]+1ll*f[j]*c(i,j)%mod)%mod;
f[i]=1ll*f[i]*qpow(qpow(2,i),mod-2)%mod;
f[i]=(f[i]+1ll*c(i,2)*qpow(2,mod-2)%mod)%mod;
f[i]=1ll*f[i]*qpow(1-qpow(qpow(2,i),mod-2)+mod,mod-2)%mod;
}
for(int i=1;i<=3000;i++) f[i]=(f[i-1]+f[i])%mod;
while(scanf("%d",&n)!=EOF) write(1ll*f[n]*qpow(n,mod-2)%mod);
return 0;
}

1006. Fantastic Magic Cube

首先考虑对于每个单位立方体开一个点,所有联通的立方体用一条边连起来,边权为点权之积。

那么切开一个大立方体相当于断掉一些变,取边权。

显然无论如何切答案都是一样的。

那么直接统计答案就好了,设\(N=n^3,a_i\)表示点权:

\[ans=\sum_{i=1}^{N}\sum_{j=i+1}^{N}a_ia_j=\dfrac{(\sum_{i=1}^{N}a_i)^2-\sum_{i=1}^{N}a_i^2}{2}
\]

那么用\(fwt\)求出每个权值出现了多少次,暴力算答案就好了。

复杂度\(O(n\log n)\)。

#include<bits/stdc++.h>
using namespace std; void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
} void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double #define pii pair<int,int >
#define vec vector<int > #define pb push_back
#define mp make_pair
#define fr first
#define sc second #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) const int maxn = 2e6+10;
const int inf = 1e9;
const lf eps = 1e-8;
const int mod = 998244353;
const int inv2 = 499122177; int f[maxn],n,N; void fwt(int *r,int op) {
for(int i=1;i<N;i<<=1)
for(int j=0;j<N;j+=i<<1)
for(int k=0;k<i;k++) {
int x=r[j+k],y=r[i+j+k];
r[j+k]=(x+y)%mod,r[i+j+k]=(x-y+mod)%mod;
if(op==-1) r[j+k]=1ll*r[j+k]*inv2%mod,r[i+j+k]=1ll*r[i+j+k]*inv2%mod;
}
} void solve() {
for(N=1;N<=n;N<<=1);
for(int i=0;i<n;i++) f[i]=1;
for(int i=n;i<N;i++) f[i]=0;
fwt(f,1);
for(int i=0;i<N;i++) f[i]=1ll*f[i]*f[i]%mod*f[i]%mod;
fwt(f,-1);int ans=0,tmp=0;
for(int i=1;i<N;i++)
ans=(ans+1ll*i*f[i]%mod)%mod,tmp=(tmp+1ll*i*i%mod*f[i]%mod)%mod;
ans=1ll*ans*ans%mod;ans=(ans-tmp+mod)%mod;
write(1ll*ans*inv2%mod);
} int main() {
while(scanf("%d",&n)!=EOF) solve();
return 0;
}

1008. Harmonious Army

二元组建图模板题。。。

#include<bits/stdc++.h>
using namespace std; #define int long long void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
} void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double #define pii pair<int,int >
#define vec vector<int > #define pb push_back
#define mp make_pair
#define fr first
#define sc second #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) const int maxn = 500+10;
const int inf = 1e18;
const lf eps = 1e-8;
const int mod = 1e9+7; int head[maxn],tot=1,s,t,n,m,r[maxn][maxn],ans;
struct edge{int to,nxt,w;}e[maxn*maxn]; void add(int u,int v,int w) {e[++tot]=(edge){v,head[u],w},head[u]=tot;}
void ins(int u,int v,int w) {add(u,v,w),add(v,u,0);} int dis[maxn]; int bfs() {
memset(dis,-1,sizeof dis);
queue<int > q;q.push(s);dis[s]=0;
while(!q.empty()) {
int x=q.front();q.pop();
for(int i=head[x];i;i=e[i].nxt)
if(e[i].w>0&&dis[e[i].to]==-1) {
dis[e[i].to]=dis[x]+1;
if(e[i].to==t) return 1;
q.push(e[i].to);
}
}return 0;
} int dfs(int x,int flow) {
if(x==t) return flow;
int used=0;
for(int v,i=head[x];i;i=e[i].nxt)
if(dis[v=e[i].to]==dis[x]+1&&e[i].w>0) {
int d=dfs(e[i].to,min(e[i].w,flow));
e[i].w-=d,e[i^1].w+=d,used+=d,flow-=d;
if(!flow) break;
}
if(!used) dis[x]=-1;
return used;
} int dinic() {int res=0;while(bfs()) res+=dfs(s,inf);return res;} void solve() {
s=n+1,t=n+2;
for(int i=1;i<=m;i++) {
int u,v,a,b,c;read(u),read(v),read(a),read(b),read(c);
ans-=(a+c)*2;
r[s][u]+=c,r[s][v]+=c,r[v][t]+=a,r[u][t]+=a;
r[u][v]+=a+c-b*2,r[v][u]+=a+c-b*2;
}
for(int i=1;i<=t;i++)
for(int j=1;j<=t;j++)
if(r[i][j]) ins(i,j,r[i][j]);
write((-dinic()-ans)/2);
} void clear() {
tot=1;ans=0;
memset(head,0,sizeof head);
memset(r,0,sizeof r);
} signed main() {
while(scanf("%lld%lld",&n,&m)!=EOF) solve(),clear();
return 0;
}

1010. Just Skip The Problem

注意到最优一定是一位一位地问有没有,所以方案数直接就是阶乘。

#include<bits/stdc++.h>
using namespace std; void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
} void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double #define pii pair<int,int >
#define vec vector<int > #define pb push_back
#define mp make_pair
#define fr first
#define sc second #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) const int maxn = 1e6+10;
const int inf = 1e9;
const lf eps = 1e-8;
const int mod = 1e6+3; int fac[maxn],n; int main() {
fac[0]=1;
for(int i=1;i<mod;i++) fac[i]=1ll*fac[i-1]*i%mod;
while(scanf("%d",&n)!=EOF) write(n==2?2:(n>=mod?0:fac[n]));
return 0;
}

1011. Keen On Everything But Triangle

拿主席树维护区间,暴力判断就好了。

因为最劣的情况是构成斐波那契数列,而斐波那契增长是指数级的,所以最多在主席树上询问\(O(\log v)\)次,\(v\)是值域。

复杂度\(O(Tn\log n\log v)\)。

#include<bits/stdc++.h>
using namespace std; void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
} void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double #define pii pair<int,int >
#define vec vector<int > #define pb push_back
#define mp make_pair
#define fr first
#define sc second #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) const int maxn = 2e5+10;
const int inf = 1e9;
const lf eps = 1e-8;
const int mod = 1e9+7;
const int N = 1e9; int n,q,rt[maxn]; struct persistance_segment_tree {
int ls[maxn*40],rs[maxn*40],s[maxn*40],seg; void insert(int &p,int pre,int l,int r,int x) {
p=++seg;ls[p]=ls[pre],rs[p]=rs[pre],s[p]=s[pre]+1;
if(l==r) return ;int mid=(l+r)>>1;
if(x<=mid) insert(ls[p],ls[pre],l,mid,x);
else insert(rs[p],rs[pre],mid+1,r,x);
} int query(int a,int b,int l,int r,int k) {
if(l==r) return l;int mid=(l+r)>>1;
if(s[rs[b]]-s[rs[a]]>=k) return query(rs[a],rs[b],mid+1,r,k);
else return query(ls[a],ls[b],l,mid,k-(s[rs[b]]-s[rs[a]]));
} void clear() {
for(int i=1;i<=seg;i++) ls[i]=rs[i]=s[i]=0;
seg=0;
}
}T; int find(int l,int r,int x) {return T.query(rt[l-1],rt[r],1,N,x);} #define ll long long void solve() {
for(int i=1,x;i<=n;i++) read(x),T.insert(rt[i],rt[i-1],1,N,x);
for(int i=1;i<=q;i++) {
int l,r;read(l),read(r);
if(r-l+1<3) {puts("-1");continue;}
int a=find(l,r,1),b=find(l,r,2),c=find(l,r,3),x=3,bo=0;
while(1) {
if(a<b+c) {bo=1;printf("%lld\n",1ll*a+b+c);break;}
if(x==r-l+1) break;
a=b,b=c,c=find(l,r,++x);
}if(!bo) puts("-1");
}
} void clear() {
T.clear();
for(int i=1;i<=n;i++) rt[i]=0;
} int main() {
while(scanf("%d%d",&n,&q)!=EOF) solve(),clear();
return 0;
}

1012. Longest Subarray

考虑排除不合法的情况,在剩下的情况取最大值。

那么对于每种颜色假设数量是\(x\),那么我们可以得到\(O(x)\)个形如当\(l\)在\(a\sim b\)之间时,\(r\)不能取\(c\sim d​\)的限制条件。

显然这可以转化成一个矩形。

那么直接扫描线就好了,复杂度\(O(Tn\log n)\)。

#include<bits/stdc++.h>
using namespace std; void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
} void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double #define pii pair<int,int >
#define vec vector<int > #define pb push_back
#define mp make_pair
#define fr first
#define sc second #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) #define iter vector<int > :: iterator const int maxn = 1e5+10;
const int inf = 1e9;
const lf eps = 1e-8;
const int mod = 1e9+7; int n,c,k,cnt;
vector<int > p[maxn]; struct l {int x,l,r,v;}r[maxn<<3]; void add(int x1,int x2,int y1,int y2) {
if(x1>x2||y1>y2) return ;
r[++cnt]=(l){x1,y1,y2,1};
r[++cnt]=(l){x2+1,y1,y2,-1};
} int cmp(l x,l y) {return x.x<y.x;} #define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1) struct Segment_Tree {
int mr[maxn<<2],tag[maxn<<2]; void build(int p,int l,int r) {
mr[p]=r;tag[p]=0;
if(l==r) return ;
build(ls,l,mid),build(rs,mid+1,r);
} void update(int p,int l,int r) {
if(tag[p]) mr[p]=-1;
else if(mr[rs]!=-1) mr[p]=mr[rs];
else mr[p]=mr[ls];
} void cover(int p,int l,int r,int x,int y,int v) {
if(x<=l&&r<=y) {
tag[p]+=v;
if(l==r) mr[p]=tag[p]?-1:r;
else update(p,l,r);
return ;
}
if(x<=mid) cover(ls,l,mid,x,y,v);
if(y>mid) cover(rs,mid+1,r,x,y,v);
update(p,l,r);
}
}T; void solve() {
T.build(1,1,n);cnt=0;
for(int i=1;i<=c;i++) p[i].clear();
for(int i=1,x;i<=n;i++) read(x),p[x].pb(i);
for(int i=1;i<=c;i++)
if(p[i].size()<k) {
for(iter x=p[i].begin();x!=p[i].end();x++)
add(1,*x,*x,n);
} else {
int sz=p[i].size();
add(1,p[i][0],p[i][0],p[i][k-1]-1);
for(int x=0;x<sz-1;x++) add(p[i][x]+1,p[i][x+1],p[i][x+1],x+k>=sz-1?n:p[i][x+k+1]-1);
}
sort(r+1,r+cnt+1,cmp);int t=1,ans=0;
for(int i=1;i<=n;i++) {
while(r[t].x==i) T.cover(1,1,n,r[t].l,r[t].r,r[t].v),t++;
if(T.mr[1]<=i) continue;
ans=max(ans,T.mr[1]-i+1);
}write(ans);
} int main() {
while(scanf("%d%d%d",&n,&c,&k)!=EOF) solve();
return 0;
}

HDU校赛 | 2019 Multi-University Training Contest 2的更多相关文章

  1. HDU校赛 | 2019 Multi-University Training Contest 6

    2019 Multi-University Training Contest 6 http://acm.hdu.edu.cn/contests/contest_show.php?cid=853 100 ...

  2. HDU校赛 | 2019 Multi-University Training Contest 5

    2019 Multi-University Training Contest 5 http://acm.hdu.edu.cn/contests/contest_show.php?cid=852 100 ...

  3. HDU校赛 | 2019 Multi-University Training Contest 4

    2019 Multi-University Training Contest 4 http://acm.hdu.edu.cn/contests/contest_show.php?cid=851 100 ...

  4. HDU校赛 | 2019 Multi-University Training Contest 3

    2019 Multi-University Training Contest 3 http://acm.hdu.edu.cn/contests/contest_show.php?cid=850 100 ...

  5. HDU校赛 | 2019 Multi-University Training Contest 1

    2019 Multi-University Training Contest 1 http://acm.hdu.edu.cn/contests/contest_show.php?cid=848 100 ...

  6. hdu 4930 Fighting the Landlords--2014 Multi-University Training Contest 6

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4930 Fighting the Landlords Time Limit: 2000/1000 MS ...

  7. HDU 6143 - Killer Names | 2017 Multi-University Training Contest 8

    /* HDU 6143 - Killer Names [ DP ] | 2017 Multi-University Training Contest 8 题意: m个字母组成两个长为n的序列,两序列中 ...

  8. HDU 6074 - Phone Call | 2017 Multi-University Training Contest 4

    看标程的代码这么短,看我的.... 难道是静态LCA模板太长了? /* HDU 6074 - Phone Call [ LCA,并查集 ] | 2017 Multi-University Traini ...

  9. HDU 6068 - Classic Quotation | 2017 Multi-University Training Contest 4

    /* HDU 6068 - Classic Quotation [ KMP,DP ] | 2017 Multi-University Training Contest 4 题意: 给出两个字符串 S[ ...

随机推荐

  1. web-api POST body object always null

      If the any of values of the request's JSON object are not the same type as expected by the service ...

  2. How to prove that SAP CRM WebUI is a stateful application

    I create an enhancement in this function module to print out current session id: As long as I do not ...

  3. 未能加载文件或程序集“Spire.Pdf, Version=4.8.8.2020, Culture=neutral, PublicKeyToken=663f351905198cb3”或它的某一个依赖项。未能授予最小权限请求

    问题:运行程序执行到代码报错:未能加载文件或程序集“Spire.Pdf, Version=4.8.8.2020, Culture=neutral, PublicKeyToken=663f3519051 ...

  4. provisional headers are shown 一例

    系统首页的ajax调用出现 报错: provisional headers are shown 最后查到的原因时,mysql数据库的磁盘满了,而首页的ajax调用要插入一条记录到数据库,卡住了.

  5. atlas笔记

    目录 环境 Mysql+Atlas配置 atlas:mysql-proxy扩展,mysql中间件,可以实现分表.分库(sharding版本).读写分离.数据库连接池等功能! Atlas类似于Twemp ...

  6. 数据分析——python基础

    前言:python数据分析的基础知识,简单总结,主要是为了方便自己写的时候查看(你们可能看不太清楚T^T),发现有用的方法,随时补充,欢迎指正 数据分析专栏: 数据分析--python基础 数据分析- ...

  7. pycharm运行过程中pycharm控制台和python控制台之间的切换

    有时候在调试(debug)python代码的时候,希望像matlab那样输入某一个变量以查看其值,这是需要把pycharm的console切换到python的console,以输入变量查看其值,点击那 ...

  8. 深度学习查看GPU实时使用情况

    1.CPU使用情况查看 动态查看 打开终端,输入: $  top按Ctrl+C退出查看. 即可看到实时的CPU使用情况. 查看版本 $ top -h 即可看到当前procps-ng的版本. 2. gp ...

  9. Andriod Studio安装及使用

    创建Andriod项目 1.下载最新版的Andriod studio 2.在 Welcome to Android Studio 窗口中,点击 Start a new Android Studio p ...

  10. 【java】字符串截取

    String a = 'abcdef';String a = a.substring(0,1); a = 'a'; substring(int beginIndex, int endIndex) be ...