2018.10.31 正睿停课训练 Day13

时间:3.5h

期望得分:100+20+10

实际得分:100+20+10

又是状态很迷的一天==

比赛链接

A Poker(期望)

题目链接

容易想到枚举每一对,算它出现在多少种情况中(即\(n/2*(n-2)!\))。

这样不会算重啊,虽然一个排列会枚举多次,但每次只算的是某一对的贡献,而不是当前排列的贡献。

然后优化一下,算每个数小于它的数、小于等于它的数分别有多少个就行了。

//29ms	1156kb
#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 300000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
#define mod 1000000007
typedef long long LL;
const int N=1e5+5; int A[N];
char IN[MAXIN],*SS=IN,*TT=IN; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
} int main()
{
int n=read();
for(int i=1; i<=n; ++i) A[i]=read();
std::sort(A+1,A+1+n), A[n+1]=-1;
LL ansA=0;
for(int i=1,now=1; i<=n; i=++now)
{
while(A[now+1]==A[i]) ++now;
ansA+=1ll*(now-i+1)*(i-1);
}
LL fac=1;
for(int i=2; i<=n-2; ++i) fac=fac*i%mod;
ansA=ansA%mod*fac%mod*(n>>1)%mod;
fac=fac*(n-1)%mod*n%mod;
printf("%lld %lld\n",ansA,((1ll*fac*(n>>1)-ansA)%mod+mod)%mod); return 0;
}

B Label(高斯消元)

题目链接

(\(w_x\)表示\(x\)的点权,\(len_v\)表示\(x\to v\)的边权)

假设当前\(w_x\)未知,\(x\)周围所有点的点权\(w_v\)已知,那么我们要最小化$$\begin{aligned}\sum_{x\to v}(w_v-w_x)^2\cdot len_v&=\sum_{x\to v}(w_v2-2w_vw_x+w_x2)\cdot len_v\&=\left(\sum len_v\right)w_x^2+\left(\sum-2len_vw_v\right)w_x+\sum len_vw_v^2\end{aligned}$$

\(\sum len_v\neq0\),这就是关于\(w_x\)的二次函数。则当$$w_x=\frac{\sum w_vlen_v}{\sum len_v}$$

时,\(x\)最优(即\(w_x\)取\(v\)的加权平均数)。

于是对每个\(w_x\)未知的\(x\),都可以列出一个方程:把已知的常数项都放到右边,对未知的\(w_v\),令\(v\)处的系数为\(-len_v\)即可。注意有重边。

另外,方程组一定有解。(感觉感性理解即可,以下可以忽略。。)

证明:

设当前函数为\(f(x_1,x_2,...,x_i,...,x_n)\)。

因为边权非负,且\(f\)存在一个有限的取值,所以\(f\)一定有一个最小值。

那么一定存在一组最小的解,满足列出的方程。否则可以调整得更小:

考虑一组最小的解\(x_1,x_2,...,x_n\)

设有\(m\)个方程,第\(i\)个方程表示\(x_i\)周围变量的加权平均。假设有一个方程不满足加权平均的话,设\(x_i'\)为\(x_i\)周围变量的加权平均,那么\(f(x_1,x_2,...,x_i',...,x_n)<f(x_1,x_2,...,x_i,...,x_n)\)(是个二次函数,所以一定存在一个点是最小值),推出矛盾。所以最小解一定满足所有方程。

同时,方程组的解是唯一的。

证明:

对于一个连通块,若有一个点的权值确定,那么解是唯一的。

具体没看懂。见图。

//54ms	2440kb
#include <cmath>
#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 300000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
#define Sqr(x) (x)*(x)
#define eps 1e-9
typedef long long LL;
const int N=505,M=60005; int Enum,H[N],nxt[M],to[M],len[M];
double w[N];
bool ok[N];
char IN[MAXIN],*SS=IN,*TT=IN; inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
}
inline void AE(int w,int u,int v)
{
if(u!=v)//自环。。
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, len[Enum]=w,
to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum, len[Enum]=w;
}
namespace G
{
double A[N][N];
void Gauss(int n)
{
for(int i=1,j=1; i<=n&&j<=n+1; ++j)
{
if(!ok[i]) {++i; continue;}
int mxrow=i;
for(int k=i+1; k<=n; ++k)
if(fabs(A[k][j])>fabs(A[mxrow][j])) mxrow=k;
if(mxrow!=i)// std::swap(A[i],A[mxrow]);//这样效率低啊
for(int k=j; k<=n+1; ++k) std::swap(A[j][k],A[mxrow][k]);
if(fabs(A[i][j])<eps) continue;
for(int k=i+1; k<=n; ++k)
if(fabs(A[k][j])>eps)
{
double t=A[k][j]/A[i][j];
for(int l=j; l<=n+1; ++l) A[k][l]-=t*A[i][l];
}
++i;
}
for(int i=n; i; --i)
{
if(!ok[i]) continue;
for(int j=i+1; j<=n; ++j) A[i][n+1]-=A[i][j]*w[j];
w[i]=A[i][n+1]/A[i][i];
}
}
} int main()
{
int n=read(),m=read();
for(int i=1; i<=m; ++i) AE(read(),read(),read());
for(int i=1; i<=n; ++i) w[i]=read();
for(int x=1; x<=n; ++x)
if(w[x]<0)
{
ok[x]=1;
for(int i=H[x],v; i; i=nxt[i])
{
if(w[v=to[i]]<0) G::A[x][v]-=len[i];//可能有重边
else G::A[x][n+1]+=1.0*w[v]*len[i];
G::A[x][x]+=len[i];
}
}
G::Gauss(n);
double ans=0;
for(int x=1; x<=n; ++x)
for(int i=H[x]; i; i=nxt[i])
ans+=Sqr(w[to[i]]-w[x])*len[i];
printf("%.10lf\n",ans*0.5); return 0;
}

C Coin(二分图染色 博弈)

题目链接

10pts:用无解/有解表示是否有无法使得所有硬币朝上的情况。

那么在一定无解的情况下,所有行列都会被选一次,所以只需判\(n+m\)的奇偶性就可以了。

30pts:只需判是否无解。

设\(r_i,c_i\)分别表示第\(i\)行/第\(i\)列是否选择,\(a_{i,j}=0(棋子朝上)/1(棋子朝下)\)。

那么要求对于每个有棋子的位置\((i,j)\),\(r_i\oplus c_j=a_{i,j}\)。

即\(a_{i,j}\)可以确定\(r_i,c_j\)是否相同。所以行列间连边,二分图染色判是否合法即可。

60pts:

我们只需要判断在有解的情况下谁能得\(3\)分。

根据前面的建模,我们可以得到一个图论模型。

对于每个连通块,我们首先可以得到一种染色方案,也就是由\(a\)个点取\(0\),\(b\)个点取\(1\)。同时将每个位置取反后也是一种合法方案,即\(b\)个点取\(1\),\(a\)个点取\(0\)。

我们记这样的连通块为\(a-b\)连通块。

对于一个连通块,我们走完第一步就能确定一个位置的取值必须是什么,也就是确定该方案的\(a,b\)分别是多少。





这个状压感觉比较nb。。

100pts:

对于每个连通块,都是一个独立的平等游戏,所以可以考虑求它的\(SG\)值。

考虑一个连通块的一种染色方案,假设该连通块一共有\(s\)个点,当前有\(s_1\)个点取\(1\),那么另一种染色方案就有\(s-s_1\)个点取\(1\)。那么当前连通块的SG值\(=\mathbb{mex}(sg(s_1),sg(s-s_1))\)。

\(sg(0)=0,sg(1)=\mathbb{mex}(sg(0))=1,sg(2)=0,sg(3)=1...\),也就是\(sg(s)=s是奇数?0:1\)。

然后把所有连通块的sg值异或起来得到\(sum\),后手必胜(拿到\(3\)分)当且仅当\(sum\)为\(0\)。

(当然不用sg函数也能想到)

//4ms	804kb
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
#define MAXIN 300000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
const int N=205,M=20005; int Enum,H[N],nxt[M],to[M],col[M],vis[N],s,s1;
char IN[MAXIN],*SS=IN,*TT=IN; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline void AE(int u,int v,int c)
{
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, col[Enum]=c;
to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum, col[Enum]=c;
}
bool DFS(int x,int fa)
{
++s, s1+=vis[x];
for(int i=H[x],v; i; i=nxt[i])
if(vis[v=to[i]]==-1)
{
vis[v]=vis[x]^col[i];
if(DFS(v,x)) return 1;
}
else if(vis[v]^vis[x]!=col[i]) return 1;
return 0;
}
void Solve()
{
Enum=0, memset(H,0,sizeof H), memset(vis,0xff,sizeof vis);
int n=read(),m=read();
for(int i=1; i<=n; ++i)
{
register char c=gc(); while(!isalpha(c)) c=gc();
switch(c) {case 'o':AE(i,1+n,0); break; case 'x':AE(i,1+n,1); break;}
for(int j=2; j<=m; ++j) switch(gc()) {case 'o':AE(i,j+n,0); break; case 'x':AE(i,j+n,1); break;}
}
int ans=0;
for(int i=1; i<=n+m; ++i)
if(vis[i]==-1)
{
s=s1=0, vis[i]=0;
if(DFS(i,i)) {printf("%d\n",(n+m)&1); return;}
s-=s1;
if(s&1 && s1&1) ans^=1;
else if(!(s&1) && !(s1&1)) ans^=0;
else ans^=2;
}
puts(ans?"3":"2");
} int main()
{
for(int T=read(); T--; Solve());
return 0;
}

考试代码

A(打表)

容易想到答案只与数的相对大小及其数量有关。

首先总分是\(n/2*n!\),如果所有数各不相同则两人都为\(n/4*n!\)。

否则,用暴力打表发现,一个数每多出现一次,设其总共出现次数为\(x\),则小M的答案减少\(1*c+2*c+...+(x-1)*x\)。

\(c\)是一个关于\(n\)的系数,打表后也能递推得到。

//39ms	1940kb
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define MAXIN 300000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
#define mod 1000000007
typedef long long LL;
const int N=1e5+5; int A[N],fac[N],ifac[N],tm[N],coef[N];
char IN[MAXIN],*SS=IN,*TT=IN; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline int FP(int x,int k)
{
int t=1;
for(; k; k>>=1,x=1ll*x*x%mod)
if(k&1) t=1ll*t*x%mod;
return t;
} int main()
{
int n=read(),n2=n>>1;
fac[0]=fac[1]=1;
for(int i=2; i<=n; ++i) fac[i]=1ll*fac[i-1]*i%mod;
for(int i=1; i<=n; ++i) A[i]=read();
if(n==2)
{
int ansA=(A[1]>A[2]?1:0)+(A[2]>A[1]?1:0),ansB=(A[1]>=A[2]?1:0)+(A[2]>=A[1]?1:0);
printf("%d %d\n",ansA,ansB);
return 0;
}
std::sort(A+1,A+1+n); A[n+1]=-1;
LL tot=1ll*n2*fac[n]%mod,ansA=tot*FP(2,mod-2)%mod; int cnt=0;
for(int i=2,t=1; i<=n+1; ++i)
if(A[i]!=A[i-1]) tm[++cnt]=t, t=1;
else ++t;
coef[2]=1, coef[4]=4;
for(int i=6; i<=n; i+=2) coef[i]=1ll*coef[i-2]*((1ll*(i-2)*(i-2)+i-4)%mod)%mod;
LL C=1ll*FP(2,mod-2)*coef[n]%mod;
for(int i=1; i<=cnt; ++i)
ansA-=C*(tm[i]-1)%mod*tm[i]%mod;
ansA=(ansA%mod+mod)%mod;
LL ansB=(mod+tot-ansA)%mod;
printf("%d %d\n",(int)ansA,(int)ansB); return 0;
}

B

#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define Sqr(x) (1ll*x*x)
typedef long long LL;
const int N=505,M=60005; int A[N],B[N],C[N],Enum,H[N],nxt[M],to[M],len[M],dgr[N]; inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
}
inline void AE(int w,int u,int v)
{
++dgr[v], to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, len[Enum]=w;
++dgr[u], to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum, len[Enum]=w;
}
void DFS(int x,int fa,int dep)
{
B[dep]=A[x];
for(int i=H[x]; i; i=nxt[i])
if(to[i]!=fa) C[dep]=len[i], DFS(to[i],x,dep+1);
}
inline double Check(double x)
{
return 1.0*(x-B[1])*(x-B[1])*C[1]+1.0*(x-B[3])*(x-B[3])*C[2];
} int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout); int n=read(),m=read(); Enum=1;
for(int i=1; i<=m; ++i) AE(read(),read(),read());
for(int i=1; i<=n; ++i) A[i]=read();
if(n==2)
{
if(A[1]==-1||A[2]==-1) puts("0.0");
else printf("%lld.0\n",1ll*len[2]*Sqr(A[1]-A[2]));
return 0;
}
int rt=1;
for(int i=1; i<=n; ++i) if(dgr[i]==1) {rt=i; break;}
DFS(rt,rt,1);
int cnt=0;
for(int i=1; i<=n; ++i) if(B[i]==-1) ++cnt;
if(cnt>=n-1) return puts("0.0"),0;
if(!cnt)
{
LL ans=0;
for(int i=1; i<n; ++i) ans+=Sqr(B[i+1]-B[i])*C[i];
printf("%lld.0\n",ans);
return 0;
}//cnt=1
if(B[1]==-1) return printf("%lld.0\n",Sqr(B[3]-B[2])*C[2]),0;
if(B[3]==-1) return printf("%lld.0\n",Sqr(B[1]-B[2])*C[1]),0;
double l=std::min(B[1],B[3]),r=std::max(B[1],B[3]),lmid,rmid,ans=1e18;
for(int T=1; T<=100; ++T)//二次函数求最值啊 我还写个三分==
{
lmid=l+(r-l)/3, rmid=r-(r-l)/3;
double x=Check(lmid),y=Check(rmid);
if(x<y) ans=std::min(ans,x), r=rmid;
else ans=std::min(ans,y), l=lmid;
}
printf("%.10lf\n",ans); return 0;
}/*
3 2
1 2 3
2 3 1
0 -1 1
*/

10.31 正睿停课训练 Day13的更多相关文章

  1. 10.29 正睿停课训练 Day11

    目录 2018.10.29 正睿停课训练 Day11 A 线段树什么的最讨厌了(思路 DFS) B 已经没有什么好害怕的了(差分 前缀和) C 我才不是萝莉控呢(DP 贪心 哈夫曼树) 考试代码 A ...

  2. 10.30 正睿停课训练 Day12

    目录 2018.10.30 正睿停课训练 Day12 A 强军战歌(DP 树状数组 容斥) B 当那一天来临(思路) C 假如战争今天爆发(贪心) 考试代码 B C 2018.10.30 正睿停课训练 ...

  3. 10.25 正睿停课训练 Day9

    目录 2018.10.25 正睿停课训练 Day9 A 数独(思路 DP) B 红绿灯(最短路Dijkstra) C 轰炸(计算几何 圆并) 考试代码 B C 2018.10.25 正睿停课训练 Da ...

  4. 10.24 正睿停课训练 Day8 AM

    目录 2018.10.24 正睿停课训练 Day8 AM A 棒棒糖(组合) B 彩虹糖(思路 博弈) C 泡泡糖(DP) 考试代码 A B C 2018.10.24 正睿停课训练 Day8 AM 期 ...

  5. 10.23 正睿停课训练 Day7

    目录 2018.10.23 正睿停课训练 Day7 A 矩形(组合) B 翻转(思路) C 求和(思路 三元环计数) 考试代码 B1 B2 C 2018.10.23 正睿停课训练 Day7 期望得分: ...

  6. 11.6 正睿停课训练 Day17

    目录 2018.11.6 正睿停课训练 Day17 A chinese(思路 计数) B physics(单调队列/剪枝 DP) C chemistry(期望 DP) 考试代码 A B C 2018. ...

  7. 11.5 正睿停课训练 Day16

    目录 2018.11.5 正睿停课训练 Day16 A 道路规划(思路) B 逻辑判断(枚举 位运算/DP 高维前缀和) C 区间(贪心/树状数组) 考试代码 A B C 2018.11.5 正睿停课 ...

  8. 11.2 正睿停课训练 Day15

    目录 2018.11.2 正睿停课训练 Day15 A 郁闷的小G(二分) B 小G的树(树形DP) C 数的距离(思路) 考试代码 B C 2018.11.2 正睿停课训练 Day15 时间:3.5 ...

  9. 11.1 正睿停课训练 Day14

    目录 2018.11.1 正睿停课训练 Day14 A 字符串 B 取数游戏(贪心) C 魔方(模拟) 考试代码 B C 2018.11.1 正睿停课训练 Day14 时间:3.5h 期望得分:100 ...

随机推荐

  1. SpringBoot整合Email(电子邮件服务)

    (1).导入starter依赖 <dependency> <groupId>org.springframework.boot</groupId> <artif ...

  2. sublime3添加python编译系统

    好记性不如烂笔头 为sublime3添加python编译系统,这里使用的anonconda2中的python.exe(即python2.7版本) 步骤: (1)打开sublime,打开“工具-> ...

  3. Redis消息通知(任务队列和发布订阅模式)

    Redis学习笔记(十)消息通知(任务队列和发布订阅模式) 1. 任务队列 1.1 任务队列的特点 任务队列:顾名思义,就是“传递消息的队列”.与任务队列进行交互的实体有两类,一类是生产者(produ ...

  4. sum行列合计

    select sum(decode(cplb,'3',hj,0)) from lr_scsjdqdw t group by zcxmdm

  5. 转载:gc的概念,如果A和B对象循环引用,是否可以被GC?

    原文:https://www.cnblogs.com/zhchoutai/p/6784929.html ①首先说一下,GC里边在JVM其中是使用的ROOT算法,ROOT算法,什么称作为ROOT呢,就是 ...

  6. 从输入url到显示网页,后台发生了什么?

    参考http://igoro.com/archive/what-really-happens-when-you-navigate-to-a-url/ http://www.cnblogs.com/we ...

  7. HDU1850 尼姆博弈求可行方案数目

    尼姆博弈(Nimm's Game) 题型 尼姆博弈模型,大致上是这样的: 有3堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取1个,多者不限,最后取光者得胜. 分析 1.首先自己想一下 ...

  8. extern "C" 回顾

    引入:在测试"extern "C" 与gcc, g++无关"时,使用到了extern "C"的概念,网上找篇文章回顾一下. 试验如下: te ...

  9. VMware虚拟机 Ubuntu 16.04 安装

    第一步:VMware虚拟机 Ubuntu 16.04 安装 第二步: 解决窗口全屏问题 linux下给root用户设置密码 修改root用户的密码 $ sudo passwd root 密码会要求重复 ...

  10. AOJ 2249 Road Construction (dijkstra)

    某国王需要修路,王国有一个首都和多个城市,需要修路.已经有修路计划了,但是修路费用太高. 为了减少修路费用,国王决定从计划中去掉一些路,但是需要满足一下两点: 保证所有城市都能连通 所有城市到首都的最 ...