2018.10.23 正睿停课训练 Day7

期望得分:100+?+40

实际得分:100+20+40

比赛链接

A 矩形(组合)

题目链接

#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define mod 1000000007
typedef long long LL;
const int N=2e5+5; int fac[N],ifac[N]; 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;
}
inline int C(int n,int m)
{
if(n<0||m<0) return 0;
return 1ll*fac[n+m]*ifac[n]%mod*ifac[m]%mod;
} int main()
{
int n=read(),m=read(),A=read(),B=read(),lim=n+m;
fac[0]=fac[1]=1;
for(int i=2; i<=lim; ++i) fac[i]=1ll*fac[i-1]*i%mod;
ifac[lim]=FP(fac[lim],mod-2);
for(int i=lim; i; --i) ifac[i-1]=1ll*ifac[i]*i%mod; LL ans=0;
if(B!=m-1)
{
for(int i=1; i<n-A; ++i)
ans+=1ll*C(m-B-2,n-i)*C(B,i-1)%mod;
ans+=1ll*C(m-B-1,A)*C(B,n-A-1)%mod;
}
else ans+=1ll*C(m-B-1,A)*C(B,n-A-1)%mod;
printf("%lld\n",ans%mod); return 0;
}

B 翻转(思路)

题目链接

AGC019 D

\(A\)左移/右移等价于\(B\)右移/左移。考虑移动\(B\)。

\(B\)显然不会反复左移右移。假设\(B\)左移了\(a\)次,然后右移\(a+b\)次,那么\(B\)中每个\(1\)就覆盖了区间\([-a,b]\)。

我们先枚举最终状态,也就是\(A[1]\)最终对应了哪个\(B[i]\)。

先令\(B\)左移\(i-1\)次。那对于此时\(A\)和\(B\)仍不相同的位置(\(A^{\wedge}B\)中\(1\)的位置),必须被\(B\)中的某个\(1\)覆盖。

枚举\(a\),再\(O(n)\)扫一遍就可以得到此时的答案\(\min\{2a+b\}\)。这样就是\(O(n^3)\)的做法。

对每个\(A,B\)不同的位置\(p\),记\(L(p)\)表示若左移\(B\)来覆盖\(p\)最少还需要多少次左移(就是\(p\)到右边最近的\(1\)的距离)("还需要"是指左移\(i\)次后),\(R(p)\)表示若右移\(B\)来覆盖\(p\)最少需要多少次右移。

那么对于每个\(p\),要么满足\(a\geq L(p)\),要么\(b\geq R(p)\)。

把所有的限制按\(L\)排序,从大到小枚举\(a\),\(b\)要满足的限制就是\(R\)的后缀最大值。

因为\(a\)最多到\(n-1\),对每个\(a\)求一个最大的\(R\),然后从大到小枚举即可,可以不排序。(排序也不影响复杂度,还更方便。。)(代码是枚举的\(b\))

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

这样枚举的是左移多少,然后算需要右移多少位。还需要枚举右移多少位。把\(A,B\ reverse\)再这样求一遍即可。

//269ms	540kb
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
typedef long long LL;
const int N=4005,INF=2e9; char A[N],B[N]; int Solve(int n)
{
static int L[N],R[N],mxR[N];
for(int i=1; i<=n; ++i) B[i+n]=B[i];
for(L[1]=0; B[n-L[1]+1]=='0'; ++L[1]);
for(int i=2; i<=n; ++i) L[i]=B[i]=='1'?0:L[i-1]+1;
for(R[n]=0; B[n+R[n]]=='0'; ++R[n]);
for(int i=n-1; i; --i) R[i]=B[i]=='1'?0:R[i+1]+1; int ans=1e9;
for(int i=0; i<n; ++i)
{
int cnt=0;
memset(mxR,0,sizeof mxR);
for(int j=1; j<=n; ++j)
if(A[j]!=B[i+j]) ++cnt, mxR[L[j]]=std::max(mxR[L[j]],R[j]-i);//<<i 右移L[j]次时,除左移i次外还需左移mxR[L[j]]次
for(int j=n-1,mx=0; ~j; --j)
ans=std::min(ans,2*j+2*mx+i+cnt), mx=std::max(mx,mxR[j]);
}
return ans;
} int main()
{
scanf("%s%s",A+1,B+1); int n=strlen(A+1),f=0;
for(int i=1; i<=n; ++i) if(B[i]=='1') {f=1; break;}
if(!f)
{
for(int i=1; i<=n; ++i) if(A[i]=='1') return puts("-1"),0;
return puts("0"),0;
}
int ans=Solve(n);
std::reverse(A+1,A+1+n), std::reverse(B+1,B+1+n);
ans=std::min(ans,Solve(n));
printf("%d\n",ans); return 0;
}

C 求和(思路 三元环计数)

题目链接

\(k=1\)时,每条边都会在\(2^{n-2}\)种方案中出现,直接输出\(m*2^{n-2}\)即可。

\(k=2\)时,令\(g(i)=[边i是否存在(i的两个端点都在s中)]\),则\(Ans=\sum_{所有方案}\left(\sum_{i=1}^mg(i)\right)^2=\sum_{所有方案}\left(\sum_{i=1}^mg(i)*\sum_{i=1}^mg(i)\right)\)。

\(\sum_{i=1}^mg(i)*\sum_{i=1}^mg(i)\)就是\(\sum_{i=1}^m\sum_{j=1}^mg(i)*g(j)\)(\(i\)可以等于\(j\)),即枚举两条边,如果它们同时存在,则贡献为\(1\)。

那么答案就是任意两条边\(e_1,e_2\)同时存在的方案数(\(e_1\)可以等于\(e_2\))。

我们枚举每一条边\(e_1\),再看一下第二条边\(e_2\)选哪条以及在多少个集合里即可。有三种情况:

\(e_1=e_2\):

\(e_1,e_2\)有一个公共端点:

\(e_1,e_2\)无公共端点:

每种情况对应有多少条边(\(e_2\))可以用度数算,且都确定了一些点必须选。设必须选\(x\)个点,则乘上\(2^{n-x}\)的系数即可。

复杂度\(O(m)\)。

\(k=3\)时,同样,计算三条边同时存在的方案数。

如果只枚举一条边,情况太多且系数不好判断。但是我们可以直接枚举三条边,然后算这三条边一共确定了哪几个点必须选(sort,unique即可),设有\(x\)个,则这三条边的贡献为\(2^{n-x}\)。

这样复杂度\(O(m^3)\)。结合暴力+上面的算法,期望得分\(80\)。

满分做法:

有心情再写。。?

太神了。。自己造些数据然后高斯消元求系数?

80分代码:

#include <cstdio>
#include <cctype>
#include <vector>
#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
#define Mod(x) x>=mod&&(x-=mod)
typedef long long LL;
const int N=1e5+5; int A[N],B[N],dgr[N],pw[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(),m=read(),K=read(); pw[0]=1;
for(int i=1; i<=n; ++i) pw[i]=pw[i-1]<<1, Mod(pw[i]);
for(int i=1; i<=m; ++i) ++dgr[A[i]=read()], ++dgr[B[i]=read()]; if(K==1) return printf("%lld\n",1ll*m*pw[n-2]%mod),0;
if(K==2)
{
LL ans=1ll*m*pw[n-2]%mod;//e1=e2
for(int i=1,d1,d2; i<=m; ++i)
{
d1=dgr[A[i]], d2=dgr[B[i]];
if(n>=3) ans+=1ll*(d1+d2-2)*pw[n-3]%mod;
if(n>=4) ans+=1ll*(m-d1-d2+1)*pw[n-4]%mod;
}
return printf("%lld\n",ans%mod),0;
}
if(K==3)
{
LL ans=0;
for(int i=1; i<=m; ++i)
for(int j=1; j<=m; ++j)
for(int k=1; k<=m; ++k)
{
int a[6]={A[i],B[i],A[j],B[j],A[k],B[k]},t;
std::sort(a,a+6), t=std::unique(a,a+6)-a;
ans+=pw[n-t];
}
return printf("%lld\n",ans%mod),0;
} return 0;
}

考试代码

B1

xjbDP。。

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
typedef long long LL;
const int N=4005,INF=2e9; int n,pre[N],nxt[N],f[N][2],g[N][2];
bool ok[N];
char A[N],B[N]; bool Check()
{
for(int i=1; i<=n; ++i) if(A[i]!=B[i]) return 0;
return 1;
}
bool Check2()
{
for(int i=1; i<=n; ++i) if(A[i]=='1') return 0;
return 1;
}
inline int Calc(int l,int r)
{
if(l<=r) return r-l;
return n-r+l;
}
int Solve1(int x)
{
int ans=x-1+(B[1]!=A[x]);//to left x-1
f[x][0]=0, f[x][1]=INF, g[x][0]=x-1, g[x][1]=0;
for(int i=x+1; i<x+n; ++i)
{
f[i][0]=f[i-1][0], f[i][1]=f[i-1][1];
g[i][0]=g[i-1][0], g[i][1]=g[i-1][1];
if(A[i]==B[i-x+1]) continue;
if(A[i]=='0'&&B[i-x+1]=='1') {++ans; continue;}
++ans; int p=i>n?i-n:i;
int tmp=std::max(Calc(pre[p],i)-g[i-1][0],0);
f[i][0]=std::min(f[i-1][0]+tmp,f[i-1][1]+2*tmp);
g[i][0]=std::max(g[i][0],Calc(pre[p],i)); tmp=std::max(Calc(i,nxt[p])-g[i-1][1],0);
f[i][1]=std::min(f[i-1][1]+tmp,f[i-1][0]+2*tmp);
g[i][1]=std::max(g[i][1],Calc(i,nxt[p]));
}
// printf("To left %d:%d\n",x-1,ans+std::min(f[x+n-1][0],f[x+n-1][1]));
return ans+std::min(f[x+n-1][0],f[x+n-1][1]);
}
int Solve2(int x)
{
int ans=n-x+1+(B[1]!=A[x]);//to right n-(x-1)
f[x][0]=INF, f[x][1]=0, g[x][0]=0, g[x][1]=n-x+1;
for(int i=x+1; i<x+n; ++i)
{
f[i][0]=f[i-1][0], f[i][1]=f[i-1][1];
g[i][0]=g[i-1][0], g[i][1]=g[i-1][1];
if(A[i]==B[i-x+1]) continue;
if(A[i]=='0'&&B[i-x+1]=='1') {++ans; continue;}
++ans; int p=i>n?i-n:i;
int tmp=std::max(Calc(pre[p],i)-g[i-1][0],0);
f[i][0]=std::min(f[i-1][0]+tmp,f[i-1][1]+2*tmp);
g[i][0]=std::max(g[i][0],Calc(pre[p],i)); tmp=std::max(Calc(i,nxt[p])-g[i-1][1],0);
f[i][1]=std::min(f[i-1][1]+tmp,f[i-1][0]+2*tmp);
g[i][1]=std::max(g[i][1],Calc(i,nxt[p]));
}
return ans+std::min(f[x+n-1][0],f[x+n-1][1]);
}/*
1010
1100 11010
10001 0101101010
1001010001
1101010010 010110110
100101001
*/
int main()
{
scanf("%s%s",A+1,B+1), n=strlen(A+1);
for(int i=1; i<=n; ++i) if(B[i]=='1') ok[i]=1;
if(Check()) return puts("0"),0; int p=0;
for(int i=1; i<=n; ++i) if(ok[i]) {p=i; break;}
if(!p&&!Check2()) return puts("-1"),0;
nxt[n+1]=p;
for(int i=n; i; --i) nxt[i]=ok[i]?i:nxt[i+1];
p=0;
for(int i=n; i; --i) if(ok[i]) {p=i; break;}
pre[0]=p;
for(int i=1; i<=n; ++i) pre[i]=ok[i]?i:pre[i-1];
for(int i=1; i<=n; ++i) A[i+n]=A[i]; int ans=INF;
for(int i=1; i<=n; ++i) ans=std::min(ans,std::min(Solve1(i),Solve2(i)));
printf("%d\n",ans==INF?-1:ans); return 0;
}

B2

#include <cstdio>
#include <cctype>
#include <bitset>
#include <cstring>
#include <algorithm>
typedef long long LL;
const int N=4005,INF=2e9; int n;
char s[N];
std::bitset<2005> a,b,f,g,g1,tmp; void to_left()
{
int flag=g[0];
g>>=1;
if(flag) g.set(n-1);
}
void to_right()
{
int flag=g[n-1];
g<<=1;
g.reset(n);
if(flag) g.set(0);
}
int work_R(int x)
{
int now=0;
for(int i=1; i<=x; ++i)
{
to_right();
tmp=g&b;
now+=tmp.count();
g^=tmp;
}
return now;
}
int work_L(int x)
{
int now=0;
for(int i=1; i<=x; ++i)
{
to_left();
tmp=g&b;
now+=tmp.count();
g^=tmp;
}
return now;
}
void Solve()
{
int ans=1e9,cnt;
for(int i=0; i<n; ++i) if(a[i]!=b[i]) f.set(i);
tmp=f&b;
cnt=tmp.count();
f^=tmp;
for(int t1,t2,i=0; i<=n; ++i)
{
g=f;
t1=work_R(i);
g1=g;
for(int j=0; j<=n; ++j)
{
g=g1;
t2=work_L(i+j);
if(!g.count()) ans=std::min(ans,cnt+t1+t2+i+(i+j)+j);
}
}
for(int t1,t2,i=0; i<=n; ++i)
{
g=f;
t1=work_L(i);
g1=g;
for(int j=0; j<=n; ++j)
{
g=g1;
t2=work_R(i+j);
if(!g.count()) ans=std::min(ans,cnt+t1+t2+i+(i+j)+j);
}
} for(int i=1; i<n; ++i)
{
f.reset();
for(int j=0; j<n; ++j)
{
int k=(j+i) % n;
if(a[k]!=b[j]) f.set(k);
}
tmp=f&b;
cnt=tmp.count();
f^=tmp;
for(int j=0,t1,t2; j<=i; ++j)
{
g=f;
t1=work_R(j);
t2=work_L(i+j);
if(!g.count()) ans=std::min(ans,cnt+t1+t2+j+(i+j));
}
for(int j=0,t1,t2; j<=(n-i-1); ++j)
{
g=f;
t1=work_L(j);
t2=work_R(n-(i-j));
if(!g.count()) ans=std::min(ans,cnt+t1+t2+j+(n-(i-j)));
}
}
printf("%d\n",ans);
} int main()
{
scanf("%s",s+1);
n=strlen(s+1);
for(int i=1; i<=n; ++i) if(s[i]=='1') a.set(i-1);
scanf("%s",s+1);
for(int i=1; i<=n; ++i) if(s[i]=='1') b.set(i-1);
Solve(); return 0;
}

C

#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
#define Mod(x) x>=mod&&(x-=mod)
typedef long long LL;
const int N=1e5+5; int n,m,K,Enum,H[N],nxt[N<<1],to[N<<1],dgr[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 void AE(int u,int v)
{
++dgr[v], to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
++dgr[u], to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
}
namespace Subtask1
{
const int N=20;
int n,m,K;
LL Ans;
bool chose[N],mp[N][N]; void DFS(int x)
{
if(x>n)
{
int ans=0;
for(int i=1; i<=n; ++i)
if(chose[i])
for(int j=i+1; j<=n; ++j)
if(chose[j]&&mp[i][j]) ++ans;
int tmp=ans;
for(int k=1; k<K; ++k) ans=1ll*ans*tmp%mod;
Ans+=ans;
return;
}
chose[x]=0, DFS(x+1), chose[x]=1, DFS(x+1);
}
void Main()
{
n=::n,m=::m,K=::K;
for(int i=1,u,v; i<=m; ++i) u=read(),v=read(),mp[u][v]=mp[v][u]=1;
DFS(1), printf("%lld\n",Ans%mod);
}
} int main()
{
Enum=1,n=read(),m=read(),K=read();
if(n<=17) return Subtask1::Main(),0;
for(int i=1; i<=m; ++i) AE(read(),read());
if(K==1)
{
int pw2=1;
for(int i=1; i<=n-2; ++i) pw2<<=1, Mod(pw2);
printf("%lld\n",1ll*m*pw2%mod);
return 0;
} return 0;
}

10.23 正睿停课训练 Day7的更多相关文章

  1. 10.31 正睿停课训练 Day13

    目录 2018.10.31 正睿停课训练 Day13 A Poker(期望) B Label(高斯消元) C Coin(二分图染色 博弈) 考试代码 A(打表) B 2018.10.31 正睿停课训练 ...

  2. 10.29 正睿停课训练 Day11

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

  3. 10.30 正睿停课训练 Day12

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

  4. 10.25 正睿停课训练 Day9

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

  5. 10.24 正睿停课训练 Day8 AM

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

  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. 在手机的浏览器上通过连接打开App

    Android系统中实现 1.在系统系统自带的浏览器中 首先做成HTML的页面,页面内容格式如下: <a href="[scheme]://[host]/[path]?[query]& ...

  2. python 历险记(四)— python 中常用的 json 操作

    目录 引言 基础知识 什么是 JSON? JSON 的语法 JSON 对象有哪些特点? JSON 数组有哪些特点? 什么是编码和解码? 常用的 json 操作有哪些? json 操作需要什么库? 如何 ...

  3. Pytorch 资料汇总(持续更新)

    1. Pytorch 论坛/网站 PyTorch 中文网 python优先的深度学习框架 Pytorch中文文档 Pythrch-CN文档地址 PyTorch 基礎篇 2. Pytorch 书籍 深度 ...

  4. Java Map 键值对排序 按key排序和按Value排序

    一.理论准备 Map是键值对的集合接口,它的实现类主要包括:HashMap,TreeMap,Hashtable以及LinkedHashMap等. TreeMap:基于红黑树(Red-Black tre ...

  5. FineReport——获取控件值和单元格值

    设置单元格的值(填报预览): //contentPane.setCellValue(1,0,"abc");//参数面板给单元格赋实际值,即可填报 contentPane.curLG ...

  6. 【前端】JS文本比较插件

    一.先上效果图 二.JS代码 /** * [文本比较插件] * 传递两个参数dom1.dom2,以dom1为基准进行比较. * 0)dom1和dom2不能都为空: * 1)如果dom1不存在,则dom ...

  7. bootstrap改变上传文件按钮样式,并显示已上传文件名

    参考博文: html中,文件上传时使用的<input type="file">的样式自定义 html中<input type="file"&g ...

  8. Promise 基础学习

    Promise 是ES6的特性之一,采用的是 Promise/A++ 规范,它抽象了异步处理的模式,是一个在JavaScript中实现异步执行的对象. 按照字面释意 Promise 具有"承 ...

  9. AOJ 0005 GCD and LCM

    题意:求两数最大公约数和最小公倍数. 类型:辗转相除法 算法:gcd(a,b)=gcd(b,a%b),lcm(a,b)=a*b/gcd(a,b). #include <cstdio> #i ...

  10. usaco 校园网

    题解: 显然当一个图上的点是一个环时能满足题目要求 那么我们来考虑怎么形成一个环 很显然的是要先缩点 缩完点就成为了森林,如何让森林成环呢? 考虑一下环上的点的入度出度一定都大于1 而连一条边可以增加 ...