AGC009

Eternal Average

奥妙重重

如果我们用树的结构来描述操作,设一个点的深度为xix_ixi​,那么一定满足∑k−xi=1\sum k^{-x_i}=1∑k−xi​=1,并且 Z=∑ai=1k−xiZ=\sum_{a_i=1}k^{-x_i}Z=∑ai​=1​k−xi​。

方便起见,我们引入kkk进制小数的概念。设Z=0.z1z2...znZ=0.z_1z_2...z_nZ=0.z1​z2​...zn​,其中ziz_izi​表示k−ik^{-i}k−i,zn≠0z_n\ne 0zn​=0 。

那么合法的小数部分{zi}\{z_i\}{zi​}应该满足:

1.11.11.1 如果不进位,那么∑i=1nzi=n\sum_{i=1}^n z_i= n∑i=1n​zi​=n
1.21.21.2 如果进位,那么∑i=1nzi≤n\sum_{i=1}^nz_i\le n∑i=1n​zi​≤n ,并且每次进位会导致数位之和减去k−1k-1k−1,∑i=1nzi≡n(modk−1)\sum_{i=1}^n z_i\equiv n\pmod {k-1}∑i=1n​zi​≡n(modk−1) 。

假设上述限制是充要的。换句话说,我们只关注ZZZ最终的形式,而不关注具体的方案。

不妨做一些逆向思考。知道了ZZZ的最终形式后,通过不断拆分高位可以得到恰好nnn个数,而根据这nnn个点的深度又可以把实际的操作树求出来。具体操作是,从根节点开始分裂,在每一层保留恰当的点数,不难自行验证。扯得有点远了

最后不要忘了∑k−xi=1\sum k^{-x_i}=1∑k−xi​=1这个条件,事实上这等价于∑ai=0k−xi=1−Z=0.(k−1−z1)(k−1−z2)...(k−zn)\sum_{a_i=0}k^{-x_i}=1-Z=0.(k-1-z_1)(k-1-z_2)...(k-z_n)∑ai​=0​k−xi​=1−Z=0.(k−1−z1​)(k−1−z2​)...(k−zn​) ,根据上述推导得出1+∑i=1n(k−1−zi)≤m1+\sum_{i=1}^n(k-1-z_i)\le m1+∑i=1n​(k−1−zi​)≤m并且1+∑i=1n(k−1−zi)≡m(modk−1)1+\sum_{i=1}^n(k-1-z_i)\equiv m\pmod {k-1}1+∑i=1n​(k−1−zi​)≡m(modk−1) 。

让我们总结一下。设dpi,jdp_{i,j}dpi,j​表示当前从高到低考虑到第iii位,数位之和为jjj的方案数。转移方程为dpi,j=∑dpi−1,j−kdp_{i,j}=\sum dp_{i-1,j-k}dpi,j​=∑dpi−1,j−k​ ,可以前缀和优化。因为zn≠0z_n\ne 0zn​=0所以可能要用0/10/10/1记录一下当前这位的状态。

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

#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define fi first
#define se second
#define db double
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
const int mod=1e9+7;
int n,m,K;
ll dp[2005][2005][2],sum[2005][2005],res;
void add(ll &x,ll y){x=(x+y)%mod;}
int main(){cin>>n>>m>>K;dp[0][0][0]=1;for(int i=0;i<=n;i++)sum[0][i]=1;for(int i=1;i<=(n+m-1)/(K-1);i++){for(int j=0;j<=n;j++){add(dp[i][j][0],dp[i-1][j][0]+dp[i-1][j][1]);if(min(K-1,j)==j)add(dp[i][j][1],sum[i-1][j-1]);else add(dp[i][j][1],sum[i-1][j-1]-sum[i-1][j-min(K-1,j)-1]);if(j%(K-1)==n%(K-1)&&i*(K-1)-j+1<=m&&(i*(K-1)-j+1)%(K-1)==m%(K-1))add(res,dp[i][j][1]);}sum[i][0]=1;for(int j=1;j<=n;j++)sum[i][j]=(sum[i][j-1]+dp[i][j][0]+dp[i][j][1])%mod;}cout<<(res+mod)%mod;
}

AGC019

Yes or No

组合数学题。

因为本人数学比较菜所以只会组合意义啦。

方便起见,我们引入坐标(x,y)(x,y)(x,y)表示当前状态。那么对于一条路径,猜对的问题数目就是蓝边的数量。


如果这条路径多次穿过y=xy=xy=x,那么我们只保留第一个交点,并对路径作对称,这样蓝边的数目并不会改变。


设交点坐标是(x,x)(x,x)(x,x),发现蓝边的数目(n−x)+x=n(n-x)+x=n(n−x)+x=n是定值!最后我们认为对角线的贡献是路径与对角线的交点数目/2

答案是n+∑i=1m(2ii)(n+m−2in−i)2(n+mn)n+\frac{\sum_{i=1}^m\binom{2i}{i}\binom{n+m-2i}{n-i}}{2\binom{n+m}{n}}n+2(nn+m​)∑i=1m​(i2i​)(n−in+m−2i​)​。

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

remark\text{remark}remark 妙处在于发现潜在的组合意义。

#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define fi first
#define se second
#define db double
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
const int mod=998244353;
int n,m;
ll fac[1000005],inv[1000005],res;
ll fpow(ll x,ll y){ll z(1);for(;y;y>>=1){if(y&1)z=z*x%mod;x=x*x%mod;}return z;
}
void init(int n){fac[0]=1;for(int i=1;i<=n;i++)fac[i]=fac[i-1]*i%mod;inv[n]=fpow(fac[n],mod-2);for(int i=n;i>=1;i--)inv[i-1]=inv[i]*i%mod;
}
ll binom(int x,int y){return fac[x]*inv[y]%mod*inv[x-y]%mod;
}
int main(){ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);cin>>n>>m;if(n<m)swap(n,m);init(2*n);for(int i=1;i<=m;i++)res=(res+binom(2*i,i)*binom(n+m-2*i,n-i)%mod)%mod;cout<<(res*fpow(binom(n+m,n),mod-2)%mod*fpow(2,mod-2)%mod+n)%mod;
}

AGC029

Wandering TKHS

考虑uuu到根节点的路径为{t1,t2,...,tk}\{t_1,t_2,...,t_k\}{t1​,t2​,...,tk​},当从tit_iti​走到ti+1t_{i+1}ti+1​时,会扩展子树内比ti+1t_{i+1}ti+1​小的节点。因此想到设dpidp_idpi​表示从iii走到faifa_ifai​时,子树内扩展了多少个点。

记F(u,v)F(u,v)F(u,v)表示从uuu到vvv的路径上不包括vvv的最大的点,那么v∈subtree(u)v\in subtree(u)v∈subtree(u)有贡献等价于F(v,u)<F(1,u)F(v,u)<F(1,u)F(v,u)<F(1,u) 。注意到F(1,u)F(1,u)F(1,u)是定值,因此只需维护F(v,u)F(v,u)F(v,u)。

考虑自底向上维护,假设x∈son(u)x\in son(u)x∈son(u),对于小于xxx的路径直接设为xxx,用(val,c)(val,c)(val,c)记录权值为valvalval的路径有ccc条,可以手写平衡树,复杂度O(nlog⁡2n)O(n\log^2 n)O(nlog2n) 。当然,线段树合并是更优秀的写法,复杂度O(nlog⁡n)O(n\log n)O(nlogn)。

#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define fi first
#define se second
#define db double
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
int n,vis[200005],dep[200005],res[200005],dis[200005],rt[200005],dp[200005],f[200005],tot;
struct node{int l,r,sum;
}t[20000005];
vector<int>g[200005];
int ask(int p,int l,int r,int ql,int qr){if(!p)return 0;if(ql<=l&&r<=qr)return t[p].sum;int mid=l+r>>1;if(qr<=mid)return ask(t[p].l,l,mid,ql,qr);if(mid<ql)return ask(t[p].r,mid+1,r,ql,qr);return ask(t[p].l,l,mid,ql,qr)+ask(t[p].r,mid+1,r,ql,qr);
}
void ins(int &p,int l,int r,int x,int y){if(!p)p=++tot;t[p].sum+=y;if(l==r)return;int mid=l+r>>1;x<=mid?ins(t[p].l,l,mid,x,y):ins(t[p].r,mid+1,r,x,y);
}
void del(int &p,int l,int r,int ql,int qr){if(!p)return;if(ql<=l&&r<=qr){p=0;return;}int mid=l+r>>1;if(ql<=mid)del(t[p].l,l,mid,ql,qr);if(mid<qr)del(t[p].r,mid+1,r,ql,qr);t[p].sum=t[t[p].l].sum+t[t[p].r].sum;
}
int merge(int p,int q){if(!p||!q)return p+q;t[p].sum+=t[q].sum;t[p].l=merge(t[p].l,t[q].l),t[p].r=merge(t[p].r,t[q].r);return p;
}
void dfs(int u,int topf){for(auto v:g[u]){if(v!=topf){dis[v]=max(dis[u],u),dep[v]=dep[u]+1,dfs(v,u);int tot=ask(rt[v],1,n,1,v-1);del(rt[v],1,n,1,v-1),ins(rt[v],1,n,v,tot+1);dp[u]+=(f[v]=ask(rt[v],1,n,1,dis[u]-1)),rt[u]=merge(rt[u],rt[v]);}}
}
void dfs2(int u,int topf,int sum){res[u]=sum+dp[u];for(auto v:g[u]){if(v!=topf)dfs2(v,u,sum+dp[u]-f[v]);}
}
signed main(){ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);cin>>n;for(int i=1;i<n;i++){int u,v;cin>>u>>v,g[u].pb(v),g[v].pb(u);}for(auto u:g[1])dfs(u,1);for(auto u:g[1])dfs2(u,1,0);for(int i=2;i<=n;i++)cout<<res[i]+dep[i]+1<<' ';
}

Construction of a tree

神仙构造题。

我们首先构造二分图,左边是nnn个节点,右边是n−1n-1n−1个集合,(u,Ei)(u,E_i)(u,Ei​)有边当且仅当u∈Eiu\in E_iu∈Ei​。

然后有解的必要条件是,对于右边任意S⊆{E1,E2,...,En−1}S\subseteq\{E_1,E_2,...,E_{n-1}\}S⊆{E1​,E2​,...,En−1​},设其对应的点集为f(S)f(S)f(S),都有∣S∣<f(S)|S|<f(S)∣S∣<f(S),否则一定会形成环。

事实上这是充要的。给出如下构造。

首先求一个大小为n−1n-1n−1的匹配。钦定左边没有被匹配的vvv为根节点,从vvv开始跑DFSDFSDFS树(首先把之前的匹配加进DFSDFSDFS树中),对于右边集合相连的两个点就在原树上连一条边。如果过程中途停止的话,当且仅当,对于所有左侧经过的点,与它们相邻的右边的点都经历过了,并且没有扩展出新点。

因为此时左边点多一个vvv,所以左边点数比右边点数多111,那么取右边边未经过的点, 它们在左侧对应的点也是未被经过的,那么f(S)=∣S∣f(S)=|S|f(S)=∣S∣,矛盾。

比较复杂。感性理解一下就好。

复杂度O(nn)O(n\sqrt{n})O(nn​) 。瓶颈在于dinic\text{dinic}dinic求最大匹配。

#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define fi first
#define se second
#define db double
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
const int N=2e6+5;
int n,m,vis[N],head[N],nxt[N],to[N],cur[N],lab[N],cap[N],tot=1,v;
int U[200005],V[200005];
queue<int>Q;
void add(int u,int v,int w){to[++tot]=v,cap[tot]=w,nxt[tot]=head[u],head[u]=tot;to[++tot]=u,cap[tot]=0,nxt[tot]=head[v],head[v]=tot;
}
bool BFS(){for(int i=0;i<2*n;i++)lab[i]=-1;Q.push(2*n);while(Q.size()){int u=Q.front();Q.pop();for(int k=head[u];k;k=nxt[k]){int v=to[k];if(lab[v]==-1&&cap[k^1]>0)lab[v]=lab[u]+1,Q.push(v);}}return lab[0]!=-1;
}
int flow(int u,int lim){if(u==2*n)return lim;int used=0;for(int k=cur[u];k;k=nxt[k]){cur[u]=nxt[k];int v=to[k];if(lab[u]==lab[v]+1&&cap[k]){int tmp=min(lim-used,cap[k]);int ret=flow(v,tmp);cap[k]-=ret,cap[k^1]+=ret,used+=ret;if(used==lim)break;}}return used;
}
int dinic(){int tot=0;while(BFS()){for(int i=0;i<=2*n;i++)cur[i]=head[i];tot+=flow(0,0x3f3f3f3f);}return tot;
}
void dfs(int u){for(int k=head[u];k;k=nxt[k]){if(to[k]==0||vis[to[k]-n])continue;int id=to[k]-n;vis[id]=1;for(int l=head[to[k]];l;l=nxt[l]){if(cap[l])m++,U[id]=u,V[id]=to[l],dfs(to[l]);}}
}
signed main(){ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);cin>>n;for(int i=1;i<=n;i++)add(0,i,1);for(int i=n+1;i<2*n;i++)add(i,2*n,1);for(int i=1;i<n;i++){int k;cin>>k;while(k--){int x;cin>>x,add(x,n+i,1);}}if(dinic()!=n-1)cout<<"-1";else{for(int k=head[0];k;k=nxt[k]){if(cap[k])v=to[k];}dfs(v);if(m!=n-1)cout<<"-1";else for(int i=1;i<n;i++)cout<<U[i]<<' '<<V[i]<<"\n";}
}

AGC035

Add and Remove

【学习笔记】AGC009/AGC019/AGC029/AGC035相关推荐

  1. PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 call

    您的位置 首页 PyTorch 学习笔记系列 PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 发布: 2017年8月4日 7,195阅读 ...

  2. 容器云原生DevOps学习笔记——第三期:从零搭建CI/CD系统标准化交付流程

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

  3. 容器云原生DevOps学习笔记——第二期:如何快速高质量的应用容器化迁移

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

  4. 2020年Yann Lecun深度学习笔记(下)

    2020年Yann Lecun深度学习笔记(下)

  5. 2020年Yann Lecun深度学习笔记(上)

    2020年Yann Lecun深度学习笔记(上)

  6. 知识图谱学习笔记(1)

    知识图谱学习笔记第一部分,包含RDF介绍,以及Jena RDF API使用 知识图谱的基石:RDF RDF(Resource Description Framework),即资源描述框架,其本质是一个 ...

  7. 计算机基础知识第十讲,计算机文化基础(第十讲)学习笔记

    计算机文化基础(第十讲)学习笔记 采样和量化PictureElement Pixel(像素)(链接: 采样的实质就是要用多少点(这个点我们叫像素)来描述一张图像,比如,一幅420x570的图像,就表示 ...

  8. Go 学习推荐 —(Go by example 中文版、Go 构建 Web 应用、Go 学习笔记、Golang常见错误、Go 语言四十二章经、Go 语言高级编程)

    Go by example 中文版 Go 构建 Web 应用 Go 学习笔记:无痕 Go 标准库中文文档 Golang开发新手常犯的50个错误 50 Shades of Go: Traps, Gotc ...

  9. MongoDB学习笔记(入门)

    MongoDB学习笔记(入门) 一.文档的注意事项: 1.  键值对是有序的,如:{ "name" : "stephen", "genda" ...

最新文章

  1. Vant简单H5 web app【小试牛刀】
  2. Java基于Socket文件传输示例
  3. Win7硬盘安装方法
  4. c++中的继承--3(多继承问题,菱形继承)
  5. 一致性哈希算法 应用
  6. tensorflow权重初始化
  7. 如何在Spring生态中玩转RocketMQ?
  8. 深圳 | 鹏程实验室研究员招收访问学生
  9. div中的p标签于img设置同一水平_HTML网页制作常用标签及说明——前端开发入门...
  10. 频率计的交流耦合和直流耦合的区别_直流电源与交流电源是什么?直流与交流之间的区别公司新闻...
  11. Windows 2003 Server R2 x64 IIS6.0 eWebEditor无法显示的问题
  12. 使用CUDA遇到的坑
  13. 决策单调性Ⅱ:斜率优化(1597: [Usaco2008 Mar]土地购买)
  14. centos rpm安装mysql5.6_CentOS 7下使用RPM安装MySQL 5.6
  15. Python ‘,=‘ 语句的使用
  16. 网址导航站收录申请登陆口大全
  17. 程序员的表白文,加点不一样的料!
  18. Java中Number类详解
  19. 目前建站系统用的比较多的几个系统(几款值得推荐的建站系统)
  20. Going Deeper with Convolutions——GoogLeNet论文翻译——中文版

热门文章

  1. 科学家发现超时空传输能量的方法
  2. Win7与Win10在局域网内共享打印机
  3. Tomcat11——Tomat集群
  4. Android 修改zxing二维码样式
  5. html个人简介个人主页网页源码期末大作业0011
  6. 鸿蒙的境界是什么,“鸿蒙”究竟为何物?扶桑树上的神祇,还是混沌的状态?...
  7. 一个心理学教授关于“挣钱”的看法!
  8. 模型检测--工具PRISM
  9. pc端高德地图获取当前位置
  10. 五大列级庄_波尔多1855年评定的列级名庄1-5级各有哪些?哪个产区的列级庄最多?...