可可大神出题,四款有趣的游戏推荐,第四个好玩/se

T1 loopers \(\color{green}{100}\)

考虑钦定 \(a_1,a_i\) 的位置,固定左边一坨,那么剩下的一坨的 \(\sum a_i\) 是一定的,记为 \(s\),那么左边边界是 \(a_1\) 或 \(a_i\) 的概率是 \(\dfrac{a_1+a_i}{s}\),另外,\(a_i\) 要有贡献一定要在 \(a_1\) 前面,那么其概率为 \(\dfrac{ai}{s}\),所以有贡献的概率就是\(\dfrac{\frac{a_i}{s}}{\frac{a_1+ai}{s}}=\dfrac{a_i}{a_1+ai}\),每个排列都是这样的,所以总的有贡献的概率就是 \(\dfrac{a_i}{a_1+ai}\),也就是期望做出贡献的次数。\(1\) 号点比较特殊,期望次数是 \(1\),所以总期望就是 \(\sum\limits_{i=2}^{n}\dfrac{a_i^2}{a_1+a_i}+a_1\)。

把左边的通分之后发现下面是总积,上面是左边的一坨连积乘上右边的一坨连积再乘 \(a_i^2\),可以 \(O(n)\) 求出前缀积和后缀积,然后只用求一个逆元,时间复杂度 \(O(n+\log n)\)。

code:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define in read()
inline int read(){
int p=0,f=1;
char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){p=p*10+c-'0';c=getchar();}
return p*f;
}
const int N=1e7+5;
const int mod=1e9+7;
inline int qpow(int a,int b){
int ans=1;
while(b){
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
inline int inv(int x){return qpow(x,mod-2);}
int n,ans,a[N],t[N],prod[N],dorp[N];
signed main(){
freopen("loopers.in","r",stdin);
freopen("loopers.out","w",stdout);
n=in,a[1]=in;
for(int i=2;i<=n;i++)
a[i]=in,t[i]=(a[1]+a[i])%mod;
prod[1]=dorp[n+1]=1;
for(int i=2;i<=n;i++)
prod[i]=prod[i-1]*t[i]%mod;
for(int i=n;i>=2;i--)
dorp[i]=dorp[i+1]*t[i]%mod;
for(int i=2;i<=n;i++)
ans=(a[i]*a[i]%mod*prod[i-1]%mod*dorp[i+1]%mod+ans)%mod;
ans=ans*inv(prod[n])%mod;
ans=(ans+a[1])%mod;
cout<<ans;
return 0;
}

T2 rewrite \(\color{red}{30}\)


T3 pockets \(\color{red}{20}\)

区间加,区间判断是否相等。

自然想到线段树维护 hash,但是由于每个点的值需要对 \(p\) 取模,所以很难维护区间加和区间修改 hash,于是我就弃了,于是我们可以把原数组转化为差分数组,这样我们就只需要维护单点修改,这样就可以暴力维护 hash 了,但这样除了判断差分数组相等还要判断第一个数是否相等,可以维护一个 \(l\) 到 \(r\) 的区间和,只要区间和模上题目给出的 \(p\) 等于 \(0\),我们就可以判断这两个数相等了。

所以只需要线段树维护区间和区间 hash,区间维护 hash 时要注意一个位置对应的基的次数。

code:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define in read()
inline int read(){
int p=0,f=1;
char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){p=p*10+c-'0';c=getchar();}
return p*f;
}
const int mod1=998244353;
const int mod2=1000000009;
const int base=131;
const int N=5e5+5;
int n,q,mod;
int A[N],a[N];
int basem1[N];
int basem2[N];
void getbasem(){
basem1[0]=basem2[0]=1;
for(int i=1;i<=n;i++)
basem1[i]=basem1[i-1]*base%mod1,
basem2[i]=basem2[i-1]*base%mod2;
}
int b1[N<<2],b2[N<<2],sum[N<<2];
void pushup(int l,int r,int p){
int mid=(l+r)>>1;
b1[p]=(b1[p<<1]*basem1[r-mid]%mod1+b1[p<<1|1])%mod1;
b2[p]=(b2[p<<1]*basem2[r-mid]%mod2+b2[p<<1|1])%mod2;
sum[p]=(sum[p<<1]+sum[p<<1|1])%mod;
}
void built(int l,int r,int p){
if(l==r){b1[p]=b2[p]=sum[p]=a[l];return ;}
int mid=(l+r)>>1;
built(l,mid,p<<1);
built(mid+1,r,p<<1|1);
pushup(l,r,p);
}
void change(int l,int r,int p,int x,int d){
if(l==r){
a[l]=(a[l]+d)%mod;
b1[p]=b2[p]=sum[p]=a[l];
return ;
}
int mid=(l+r)>>1;
if(x<=mid)change(l,mid,p<<1,x,d);
else change(mid+1,r,p<<1|1,x,d);
pushup(l,r,p);
}
int query1(int l,int r,int p,int ql,int qr,int mr){
if(l>=ql&&r<=qr){return b1[p];}
int res=0,mid=(l+r)>>1;
if(ql<=mid&&qr>mid)
res=(query1(mid+1,r,p<<1|1,ql,qr,mr)+basem1[mr-mid]*query1(l,mid,p<<1,ql,qr,mid)%mod1)%mod1;
else if(ql<=mid)res=query1(l,mid,p<<1,ql,qr,mr);
else if(qr>mid)res=query1(mid+1,r,p<<1|1,ql,qr,mr);
return res;
}
int query2(int l,int r,int p,int ql,int qr,int mr){
if(l>=ql&&r<=qr){return b2[p];}
int res=0,mid=(l+r)>>1;
if(ql<=mid&&qr>mid)
res=(query2(mid+1,r,p<<1|1,ql,qr,mr)+basem2[mr-mid]*query2(l,mid,p<<1,ql,qr,mid)%mod2)%mod2;
else if(ql<=mid)res=query2(l,mid,p<<1,ql,qr,mr);
else if(qr>mid)res=query2(mid+1,r,p<<1|1,ql,qr,mr);
return res;
}
int querysum(int l,int r,int p,int ql,int qr){
if(l>=ql&&r<=qr){return sum[p];}
int res=0,mid=(l+r)>>1;
if(ql<=mid)res=(res+querysum(l,mid,p<<1,ql,qr))%mod;
if(qr>mid)res=(res+querysum(mid+1,r,p<<1|1,ql,qr))%mod;
return res;
}
signed main(){
n=in,q=in,mod=in;getbasem();
for(int i=1;i<=n;i++)A[i]=in,a[i]=(A[i]-A[i-1]+mod)%mod;
built(1,n,1);
for(int i=1;i<=q;i++){
int opt=in,l=in,r=in,k=in;
if(opt==1){change(1,n,1,l,k);if(r+1<=n)change(1,n,1,r+1,mod-k);}
if(opt==2){
int ql1=query1(1,n,1,l+1,l+k-1,l+k-1),qr1=query1(1,n,1,r+1,r+k-1,r+k-1);
int ql2=query2(1,n,1,l+1,l+k-1,l+k-1),qr2=query2(1,n,1,r+1,r+k-1,r+k-1);
int temp=querysum(1,n,1,l+1,r);
if(k==1&&temp%mod==0)cout<<"ye5\n";
else if(temp%mod||ql1^qr1||ql2^qr2)cout<<"n0\n";
else cout<<"ye5\n";
}
}
return 0;
}

T4 dohnadohna \(\color{red}{10}\color{white}{好玩捏}\)

暴力枚举删去每个点然后做背包有30,考虑求出 \(DAG\) 的任意拓扑序,那么拓扑序小的只能走到拓扑序大的。求出从 \(1\) 和 \(n\) 出发到每个点的 背包dp 值,然后枚举每条边,这条边两端点拓扑序跨过的点就不会对这条路径产生影响,合并两端 dp 值,线段树区间维护即可。可能会有某些点拓扑序在 \(1\) 和 \(n\) 之外,需要特殊处理。

写了一个下午,调了一个晚上

计算两个 dp 的时候如果写四个一维数组又长又丑不好调,看了可可大神的 std,学会了结构体的灵活使用,也可以当做 trick 来看。

合并 dp 值时有个细节或者 trick,如果两个 dp 第二维都是不需要填满背包容量就会统计到重复方案,如果第二维都是背包恰好的大小,统计的时间复杂度又无法保证,我们将第一个 dp 设为背包容量,第二个设为恰好,这样是不重不漏的。

刚开始写的丑写挂了,照着 std 修改了前面预处理 dp 的部分,发现了很多细节。万幸线段树没写挂。

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define in read()
inline int read(){
int p=0,f=1;
char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){p=p*10+c-'0';c=getchar();}
return p*f;
}
const int N=1e5+5;
const int M=5e5+5;
const int K=105;
const int mod=1e9+7;
inline int add(int x,int y){int z=x+y;return z>mod?z-mod:z;}
inline int mul(int x,int y){int z=x*y;return z>mod?z%mod:z;}
int n,m,k;
int a[N],b[N];
struct llmmkk{
int u,v;
}E[M];
struct edge{
int v,nxt;
}e[M];
int head[N],en;
inline void insert(int u,int v){
e[++en].v=v;
e[en].nxt=head[u];
head[u]=en;
}
int gin[N];
int id[N],wc[N],sign;
queue<int>q;
struct node{
int dis,cnt;
node(int _dis=-1,int _cnt=0):dis(_dis),cnt(_cnt){}
void check(const node &a){
if(a.dis>dis)dis=a.dis,cnt=a.cnt;
else if(a.dis==dis)cnt=add(cnt,a.cnt);
}
friend inline node operator +(const node &a,const node &b){
return node(a.dis+b.dis,mul(a.cnt,b.cnt));
}
friend inline node operator +(const node &a,const int &b){
return node(a.dis+b,a.cnt);
}
}fr[N][K],ba[N][K],ans[N];
void getid(){
for(int i=1;i<=n;i++)
if(!gin[i])q.push(i);
while(!q.empty()){
int u=q.front();q.pop();
id[u]=++sign,wc[sign]=u;
for(int i=head[u];i;i=e[i].nxt){
gin[e[i].v]--;
if(!gin[e[i].v])q.push(e[i].v);
}
}
}
inline void getdis1(){
memset(head,0,sizeof(head));en=0;
for(int i=1;i<=m;i++){
int u=E[i].u,v=E[i].v;
insert(v,u);
}
for(int i=1;i<=n;i++){
int u=wc[i];
if(u==1)fr[u][0]=node(0,1),fr[u][a[u]]=node(b[u],1);
for(int i=head[u],v=e[i].v;i;i=e[i].nxt,v=e[i].v)
for(int j=0;j<=k;j++){
if(fr[v][j].dis==-1)continue;
fr[u][j].check(fr[v][j]);
if(j+a[u]>k)continue;
fr[u][j+a[u]].check(fr[v][j]+b[u]);
}
}
}
inline void getdis2(){
memset(head,0,sizeof(head));en=0;
for(int i=1;i<=m;i++){
int u=E[i].u,v=E[i].v;
insert(u,v);
}
for(int i=n;i>=1;i--){
int u=wc[i];
if(u==n)ba[u][0]=node(0,1),ba[u][a[u]]=node(b[u],1);
for(int i=head[u],v=e[i].v;i;i=e[i].nxt,v=e[i].v)
for(int j=0;j<=k;j++){
if(ba[v][j].dis==-1)continue;
ba[u][j].check(ba[v][j]);
if(j+a[u]>k)continue;
ba[u][j+a[u]].check(ba[v][j]+b[u]);
}
}
}
int maxn[N<<2],cnt[N<<2];
int tag[N<<2],ctag[N<<2];
void pushup(int p){
if(maxn[p<<1]<maxn[p<<1|1])maxn[p]=maxn[p<<1|1],cnt[p]=cnt[p<<1|1];
else if(maxn[p<<1]>maxn[p<<1|1])maxn[p]=maxn[p<<1],cnt[p]=maxn[p<<1];
else maxn[p]=maxn[p<<1|1],cnt[p]=add(cnt[p<<1],cnt[p<<1|1]);
}
void built(int l,int r,int p){
if(l==r){maxn[p]=-0x7fffffff,cnt[p]=0;return ;}
int mid=(l+r)>>1;
built(l,mid,p<<1);
built(mid+1,r,p<<1|1);
pushup(p);
}
void f(int p,int d,int cd){
if(maxn[p]==d)cnt[p]=add(cnt[p],cd);
if(maxn[p]<d)maxn[p]=d,cnt[p]=cd;
if(d>tag[p])tag[p]=d,ctag[p]=cd;
else if(d==tag[p])ctag[p]=add(ctag[p],cd);
}
void pushdown(int l,int r,int p){
if(tag[p]){
int mid=(l+r)>>1;
f(p<<1,tag[p],ctag[p]);
f(p<<1|1,tag[p],ctag[p]);
tag[p]=0,ctag[p]=0;
}
}
void change(int l,int r,int p,int cl,int cr,int Maxn,int Cnt){
if(l>=cl&&r<=cr){f(p,Maxn,Cnt);return ;}
int mid=(l+r)>>1;pushdown(l,r,p);
if(cl<=mid)change(l,mid,p<<1,cl,cr,Maxn,Cnt);
if(cr>mid)change(mid+1,r,p<<1|1,cl,cr,Maxn,Cnt);
pushup(p);
}
bool no[N];
int ans1[N],ans2[N];
void out(int l,int r,int p){
if(l==r){
if(maxn[p]!=-0x7fffffff)
ans1[wc[l]]=maxn[p],ans2[wc[l]]=cnt[p];
else no[wc[l]]=1;
return ;
}
int mid=(l+r)>>1;pushdown(l,r,p);
out(l,mid,p<<1);out(mid+1,r,p<<1|1);
}
signed main(){
n=in,m=in,k=in;
for(int i=1;i<=n;i++)
a[i]=in,b[i]=in;
for(int i=1;i<=m;i++){
E[i].u=in,E[i].v=in;
int u=E[i].u,v=E[i].v;
insert(u,v);
gin[v]++;
}
getid();
getdis1();
getdis2();
for(int i=1;i<=n;i++)
for(int j=1;j<=k;j++)
fr[i][j].check(fr[i][j-1]);
built(1,n,1);
for(int i=1;i<=m;i++){
int u=E[i].u,v=E[i].v;node tans;
if(id[u]+1>id[v]-1)continue;
for(int j=0;j<=k;j++)
if(fr[u][j].dis!=-1&&ba[v][k-j].dis!=-1)
tans.check(fr[u][j]+ba[v][k-j]);
if(tans.dis==-1)continue;
change(1,n,1,id[u]+1,id[v]-1,tans.dis,tans.cnt);
}
if(id[1]>1)change(1,n,1,1,id[1]-1,fr[n][k].dis,fr[n][k].cnt);
if(id[n]<n)change(1,n,1,id[n]+1,n,fr[n][k].dis,fr[n][k].cnt);
cout<<fr[n][k].dis<<" "<<fr[n][k].cnt<<"\n";
out(1,n,1);
for(int i=1;i<=n;i++)
if(no[i])cout<<"-1\n";
else cout<<ans1[i]<<" "<<ans2[i]<<"\n";
return 0;
}

21.10.18 test的更多相关文章

  1. Groovy轻松入门——通过与Java的比较,迅速掌握Groovy (更新于2008.10.18)

    摘自: http://www.blogjava.net/BlueSUN/archive/2007/03/10/103014.html Groovy轻松入门--通过与Java的比较,迅速掌握Groovy ...

  2. ZT 感触的屌丝职场记 投递人 itwriter 发布于 2013-05-27 09:21 评论(18) 有3402人阅读 原文链接 [收藏] « »   作者@幻想哥呀幻想哥   有一位屌丝男,从小抱着报效祖国的理想上了大学,毕业后干了 IT 行业,高中那时候看文汇报说,搞 IT 的在上

    屌丝职场记 投递人 itwriter 发布于 2013-05-27 09:21 评论(18) 有3402人阅读  原文链接  [收藏]  « » 作者@幻想哥呀幻想哥 有一位屌丝男,从小抱着报效祖国的 ...

  3. 背水一战 Windows 10 (18) - 绑定: 与 Element 绑定, 与 Indexer 绑定, TargetNullValue, FallbackValue

    [源码下载] 背水一战 Windows 10 (18) - 绑定: 与 Element 绑定, 与 Indexer 绑定, TargetNullValue, FallbackValue 作者:weba ...

  4. 2016年12月15日 星期四 --出埃及记 Exodus 21:10

    2016年12月15日 星期四 --出埃及记 Exodus 21:10 If he marries another woman, he must not deprive the first one o ...

  5. 九月 26, 2017 10:18:14 上午 com.sun.jersey.server.impl.application.RootResourceUriRules <init> 严重: The ResourceConfig instance does not contain any root resource classes.

    Tomcat启动错误:九月 26, 2017 10:18:14 上午 com.sun.jersey.server.impl.application.RootResourceUriRules <i ...

  6. [java面试]逻辑推理6 10 18 32 下一个数?编程实现输入任意一个N位置,该数是多少?java实现

    题目: 6 10 18 32 下一个数?编程实现输入任意一个N位置,该数是多少? 10 = 6 + 4         4 18 = 10 + 8        4 + 4  32 = 18 + 14 ...

  7. Java的课后作业——18.10.18

    日期:2018.10.18 星期四 博客期:020 小试验任务: 我就发一下代码好了!!! package test1; import java.util.Scanner; public class ...

  8. First Scrum Meeting (2015/10/18)

    会议是在昨晚进行的,本来早就应该写博了,可惜今天校园网炸个不停= =.刚修好就赶紧来发博客. 会议基本要素 会议主题:爬虫项目的核心技术讨论以及项目初期的工作分配 会议时间:2015.10.18 19 ...

  9. 对于最近的一些日常总结by520(17.10.18)

    ---天天考试,各种题型都有,学到了很多新的知识,也发现了自己的许多不足---1.首先,自己的搜索需要加强,特别是广搜,10.18的T1裸广搜没有做对.2.数学的思维和一些逻辑问题需要加强,然后就是要 ...

随机推荐

  1. Linux学习笔记--快捷键

    桌面 ALT+空格 打开窗口菜单 ALT+F1 聚焦到桌面左侧任务导航栏,可按上下键导航 ALT+F2     运行命令 ALT+F4 关闭窗口 ALT+TAB 切换程序窗口 PRINT 桌面截图 S ...

  2. 【第十四篇】- Maven 自动化构建之Spring Cloud直播商城 b2b2c电子商务技术总结

    Maven 自动化构建 自动化构建定义了这样一种场景: 在一个项目成功构建完成后,其相关的依赖工程即开始构建,这样可以保证其依赖项目的稳定. 比如一个团队正在开发一个项目 bus-core-api, ...

  3. PyTorch学习笔记6--案例2:PyTorch神经网络(MNIST CNN)

    上一节中,我们使用autograd的包来定义模型并求导.本节中,我们将使用torch.nn包来构建神经网络. 一个nn.Module包含各个层和一个forward(input)方法,该方法返回outp ...

  4. C#委托与事件实用场景

    首先,我们需要知道,到底在什么情况下必须使用委托和事件呢? 请看下面的场景:首领A要搞一场鸿门宴,吩咐部下B和C各自带队埋伏在屏风两侧,约定以杯为令:若左手举杯,则B带队杀出:若右手举杯,则C带队杀出 ...

  5. ECDSA—模逆模块

    在有限域Fp上的非零元素a的逆记为a-1mod p .即在有限域Fp上存在唯一的一个元素x,使得ax恒等于1(mod p),则元素x为a的逆a-1 .本次设计采用扩展的整数Euclidean算法来求逆 ...

  6. PHP的命令行扩展Readline相关函数学习

    PHP 作为一个 Web 开发语言,相对来说,命令行程序并不是它的主战场.所以很多年轻的 PHP 开发者可能连命令行脚本都没有写过,更别提交互式的命令操作了.而今天,我们带来的这个扩展就是针对 PHP ...

  7. dede5.7 给栏目添加上缩略图

    如我们一个栏目列表都用缩略图来表示,而不仅仅只是文字,如果没有这项功能会非常麻烦,网上有很多这方面的资料,但是都试过了有很多问题,自己研究一下,测试基本通过.新加字段 typeimg后台执行SQL: ...

  8. 一文让你彻底理解group by和聚合函数

    知道group by是进行分组查询,但是一直觉得对其理解得不够透彻,在网上扒了一篇文章,我认为写得非常好. 为什么不能够select * from Table group by id,为什么一定不能是 ...

  9. VMware虚拟机常见问题(针对目前我所学的而言,还会不断更新)

    VMware虚拟机常见问题(针对目前我所学的而言,还会不断更新) 自己电脑的telnet Client是否打开 在控制面板->程序->打开或关闭Windows功能 虚拟机的telnet是否 ...

  10. CF235D-Graph Game【LCA,数学期望】

    正题 题目链接:https://www.luogu.com.cn/problem/CF235D 题目大意 给出一棵基环树,每次随机选择一个点让权值加上这个点的连通块大小然后删掉这个点. 求删光所有点时 ...