Codeforces 1528D It's a bird! No, it's a plane! No, it's AaParsa!(*2500)

考虑以每个点为源点跑一遍最短路,每次取出当前距离最小的点然后更新一圈周围的点,具体更新方法是:设 \(p\) 为当前这一轮我们取出的点,那么显然对于一条本来由 \(p\to q\),权值为 \(c\) 的边以及另一个点 \(r\),有 \(d_r\leftarrow\min(d_r,c+d_p+(r-q+d_p)\bmod n)\),直接松弛单次复杂度平方,显然过劣,稍微想想可以发现这东西等价于圆周上的距离,因此顺时针扫两遍即可线性松弛。注意由于这题边数可以达到 \(n^2\),是个稠密图,因此加上堆优化复杂度反而多一个 \(\log\),应用不带堆优化的 dijkstra,总复杂度 \(n^3\)。

const int MAXN=600;
int n,m,c[MAXN+5][MAXN+5];
bool vis[MAXN+5];ll d[MAXN+5][MAXN+5];
int get(int x){return (x>=n)?(x-n):x;}
int main(){
scanf("%d%d",&n,&m);
memset(c,63,sizeof(c));memset(d,63,sizeof(d));
for(int i=1,u,v,w;i<=m;i++) scanf("%d%d%d",&u,&v,&w),chkmin(c[u][v],w);
for(int i=0;i<n;i++){
d[i][i]=0;memset(vis,0,sizeof(vis));
for(int j=0;j<n;j++){
int p=n;
for(int k=0;k<n;k++) if(!vis[k]&&d[i][k]<d[i][p]) p=k;
vis[p]=1;int mn=INF,rem=d[i][p]%n;
for(int k=0;k<n*2;k++){
++mn;
chkmin(mn,c[p][get(get(k)-rem+n)]);
chkmin(d[i][get(k)],d[i][p]+mn);
}
}
for(int j=0;j<n;j++) printf("%lld%c",d[i][j]," \n"[j==n-1]);
}
return 0;
}

Codeforces 1528E Mashtali and Hagh Trees(*2900)

首先手玩几组数据可以发现一棵有向树满足第三个条件(也就是那个朋友的条件)当且仅当它是一棵外向树或是一棵内向树或是一个外向树与一个内向树用一条内向树根指向外向树根的边相连。考虑如何算之:

  • 外向树与内向树求法是相同的,对于每棵外向树如果把其所有边都反向,即可形成一棵内向树,因此外向树个数 \(=\) 内向树个数,而一条有向链即是外向树也是内向树,因此第一、二类树的个数总和就是符合要求的外向树个数的两倍减 \(1\)。我们设 \(dp_i\) 表示有多少棵不同构的树满足最大深度为 \(i\) 且每个点儿子个数 \(\le 2\)(根节点深度为 \(0\)),转移就分根有一个儿子和根有两个儿子即可,即 \(dp_i=dp_{i-1}+\sum\limits_{j=0}^{i-2}dp_jdp_{i-1}+\dfrac{dp_{i-1}(dp_{i-1}+1)}{2}\)。那么由于根节点儿子个数可以达到 \(3\),因此最大深度为 \(n\) 的内向树个数需进行一些分类讨论:

    • 如果根节点儿子个数 \(\le 1\),方案数就是 \(dp_n\)。
    • 如果根节点儿子个数 \(=2\),那么设根节点三个儿子最大深度分别为 \(a,b,c(a\le b\le c)\),那么必须有 \(c=n\)。但是由于 \(\le\) 这个条件的存在,有可能会算重,需要分 \(a<b<c,a=b<c,a<b=c,a=b=c\) 四种情况再进行分类讨论。
  • 对于第三种情况,我们定义一个点的深度为入度为 \(0\) 的点到其的最长距离,那么我们考虑枚举第一个入度 \(\ge 2\) 的点的深度 \(x\),那么根向树的方案数为 \(dp_x-dp_{x-1}\),减掉的那个 \(dp_{x-1}\) 是该节点入度为 \(1\) 的情况,叶向树的方案数为 \(dp_{n-1-x}-1\),减掉的那个 \(1\) 是一条链的情况,这时候的贡献已经在叶向树中计算过了。

时间复杂度线性。

const int INV2=MOD+1>>1;
const int INV6=(MOD+1)/6;
const int MAXN=1e6;
int n,dp[MAXN+5];
int main(){
scanf("%d",&n);dp[0]=1;
for(int i=1,sum=0;i<=n;i++){
dp[i]=1ll*dp[i-1]*sum%MOD;
dp[i]=(dp[i]+1ll*dp[i-1]*(dp[i-1]+1)%MOD*INV2)%MOD;
dp[i]=(dp[i]+dp[i-1])%MOD;sum=(sum+dp[i-1])%MOD;
// printf("%d %d\n",i,dp[i]);
} int ss=0;
for(int i=0,s=0;i<n-1;i++){
ss=(ss+1ll*s*dp[i])%MOD;
s=(s+dp[i])%MOD;
} int res=1ll*ss*dp[n-1]%MOD;
for(int i=0;i<n-1;i++) res=(res+1ll*dp[n-1]*dp[i]%MOD*(dp[i]+1)%MOD*INV2)%MOD;
for(int i=0;i<n-1;i++) res=(res+1ll*dp[n-1]*(dp[n-1]+1)%MOD*INV2%MOD*dp[i])%MOD;
res=(res+1ll*dp[n-1]*(dp[n-1]-1)%MOD*(dp[n-1]-2)%MOD*INV6)%MOD;
res=(res+1ll*dp[n-1]*(dp[n-1]-1))%MOD;res=(res+dp[n-1])%MOD;
res=(res+dp[n])%MOD;res=(res*2)%MOD;
for(int i=1;i<n-1;i++) res=(res+1ll*(dp[i]-1)*(dp[n-1-i]-dp[n-2-i]+MOD))%MOD;
printf("%d\n",(res-1+MOD)%MOD);
return 0;
}

Codeforces 1511F Chainword(*2700)

因为昨天做过了这场的 G,今天就顺便把 F 做了(

这道题就很套路了吧。。。

建出 \(n\) 个串的 trie,然后设 \(dp_{i,j}\) 表示目前第一段拼成的串的长度为 \(i\),第二段划分到 trie 树上第 \(j\) 个节点的方案数,然后发现转移只会从前面 \(5\) 个位置转移过来,于是开一个 \(5\times 5\times 8\) 的矩阵维护转移情况即可。由于字符串长度很小,转移矩阵可以大力暴搜求出。然后矩阵快速幂即可。

时间复杂度 \(|S|^6n^3\log m\)。

const int MAXN=8;
const int MAXP=41;
const int MAXL=5;
const int MAXS=215;
int n,m,ch[MAXP+5][27],ncnt=1,tot,ed[MAXP+5];
string s[MAXN+2];
void insert(string str){
int cur=1;
for(int i=0;i<str.size();i++){
if(!ch[cur][str[i]-'a']) ch[cur][str[i]-'a']=++ncnt;
cur=ch[cur][str[i]-'a'];
} ed[cur]=1;
}
struct mat{
u64 a[MAXS+5][MAXS+5];
mat(){memset(a,0,sizeof(a));}
mat operator *(const mat &rhs){
mat res;
for(int i=1;i<=tot;i++) for(int k=1;k<=tot;k++) for(int j=1;j<=tot;j++){
res.a[i][j]+=a[i][k]*rhs.a[k][j];
if((k&15)==0) res.a[i][j]%=MOD;
}
for(int i=1;i<=tot;i++) for(int j=1;j<=tot;j++) res.a[i][j]%=MOD;
return res;
}
void print(){
for(int i=1;i<=tot;i++) for(int j=1;j<=tot;j++)
printf("%llu%c",a[i][j]," \n"[j==tot]);
}
} trs,res;
int a[MAXL+2][MAXP+5][MAXP+5];
void dfsclc(int p,int id,int len,int ori){
if(ed[p]&&len!=0) dfsclc(1,id,len,ori);
if(len==s[id].size()) return a[len][ori][p]++,void();
if(ch[p][s[id][len]-'a']) dfsclc(ch[p][s[id][len]-'a'],id,len+1,ori);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
static char orzczx[MAXL+4];
scanf("%s",orzczx+1);int len=strlen(orzczx+1);
for(int j=1;j<=len;j++) s[i].pb(orzczx[j]);
insert(s[i]);
} tot=ncnt*5;
for(int i=1;i<=ncnt;i++) for(int j=1;j<=n;j++) dfsclc(i,j,0,i);
for(int i=1;i<=4;i++) for(int j=1;j<=ncnt;j++) trs.a[j+i*ncnt][j+(i-1)*ncnt]=1;
for(int i=1;i<=5;i++) for(int j=1;j<=ncnt;j++) for(int k=1;k<=ncnt;k++)
trs.a[(5-i)*ncnt+j][4*ncnt+k]=a[i][j][k];
// trs.print();
for(int i=1;i<=tot;i++) res.a[i][i]=1;
for(;m;m>>=1,trs=trs*trs) if(m&1) res=res*trs;
printf("%d\n",res.a[4*ncnt+1][4*ncnt+1]);
return 0;
}

Codeforces 1495D BFS Trees(*2600)

先考虑怎样求出一个点 \(x\) 的 BFS Tree 的数量。考虑将点按 \(x\) 到其的最短距离分层,那么显然每个点在 BFS Tree 上的父亲必须是某个上一层的节点,而如果我们钦定每个点都连向一个上一层的节点,那显然会形成一个树形结构,因此方案数就是对于与每个不同于源点的点 \(x\),与其相连的在其上一层的节点个数之积。

接下来考虑求解原问题。注意到对于两个点 \(i,j\),如果存在两个不同的点 \(x,y\),满足 \(dis_{i,x}+dis_{x,j}=dis_{i,j},dis_{i,y}+dis_{y,j}=dis_{i,j}\),且 \(dis_{i,x}=dis_{i,y}\) 那么答案肯定是 \(0\),因为 \(i\to x,x\to j,i\to y,y\to j\) 最短路上的节点肯定都要在 BFS Tree 上,这样构不成树形结构,否则对于在 \(i,j\) 最短路径上的点,它们之间的连边情况肯定是唯一的,我们就把它们缩起来然后跑前面的子问题即可。

实现时不必真的缩,只用统计对于某个不在 \(i,j\) 最短路上的点 \(x\),有多少个与之相连的点 \(y\) 满足 \(dis_{i,x}=dis_{i,y}+1,dis_{j,x}=dis_{j,y}+1\)。

时间复杂度 \(n^2m\)。

const int MAXN=400;
const int MAXM=600;
int n,m,dis[MAXN+5][MAXN+5];
link_list<int,MAXN,MAXM*2> g;
bool vis[MAXN+5];
int main(){
scanf("%d%d",&n,&m);memset(dis,63,sizeof(dis));
for(int i=1;i<=n;i++) dis[i][i]=0;
for(int i=1,u,v;i<=m;i++){
scanf("%d%d",&u,&v);dis[u][v]=dis[v][u]=1;
g.ins(u,v);g.ins(v,u);
}
for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
chkmin(dis[i][j],dis[i][k]+dis[k][j]);
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){
memset(vis,0,sizeof(vis));bool ban=0;
for(int k=1;k<=n;k++) if(dis[i][j]==dis[i][k]+dis[k][j]){
if(vis[dis[i][k]]){ban=1;break;}
vis[dis[i][k]]=1;
} int res=1;
if(!ban){
for(int k=1;k<=n;k++) if(dis[i][j]!=dis[i][k]+dis[k][j]){
int cnt=0;
for(int e=g.hd[k];e;e=g.nxt[e]){
int f=g.val[e];
if(dis[i][f]+1==dis[i][k]&&dis[j][f]+1==dis[j][k]) cnt++;
} res=1ll*res*cnt%MOD;
}
} printf("%d%c",(ban)?0:res," \n"[j==n]);
}
return 0;
}

2021.9.30 Codeforces 中档题四道的更多相关文章

  1. Codeforces 杂题集 2.0

      记录一些没有写在其他随笔中的 Codeforces 杂题, 以 Problemset 题号排序   1326D2 - Prefix-Suffix Palindrome (Hard version) ...

  2. 2021.11.30 eleveni的水省选题的记录

    2021.11.30 eleveni的水省选题的记录 因为eleveni比较菜,eleveni决定先刷图论,再刷数据结构,同时每天都要刷dp.当然,对于擅长的图论,eleveni决定从蓝题开始刷.当然 ...

  3. 2021.08.30 前缀函数和KMP

    2021.08.30 前缀函数和KMP KMP算法详解-彻底清楚了(转载+部分原创) - sofu6 - 博客园 (cnblogs.com) KMP算法next数组的一种理解思路 - 挠到头秃 - 博 ...

  4. Codeforces刷题计划

    Codeforces刷题计划 已完成:-- / -- [Codeforces370E]370E - Summer Reading:构造:(给定某些数,在空白处填数,要求不下降,并且相邻差值<=1 ...

  5. FFT/NTT中档题总结

    被DeepinC%怕了,把一些题放到这里来 T1Normal 其实这道题放到中档题也不太合适,个人感觉真的很难,机房里好像都是颓的题解 因为期望的可加性,把每个点的贡献单独处理,即求期望深度 考虑$y ...

  6. Educational Codeforces Round 30 A[水题/数组排序]

    A. Chores time limit per test 2 seconds memory limit per test 256 megabytes input standard input out ...

  7. Codeforces 939A题,B题(水题)

    题目链接:http://codeforces.com/problemset/problem/939/A A题 A. Love Triangle time limit per test 1 second ...

  8. Codeforces水题集合[14/未完待续]

    Codeforces Round #371 (Div. 2) A. Meeting of Old Friends |B. Filya and Homework A. Meeting of Old Fr ...

  9. 屏蔽Codeforces做题时的Problem tags提示

    当在Codeforces上做题的时,有时会无意撇到右侧的Problem tags边栏,但是原本并不希望能够看到它. 能否把它屏蔽了呢?答案是显然的,我们只需要加一段很短的CSS即可. span.tag ...

随机推荐

  1. 解决pip._vendor.urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host='files.pythonhosted.org', port=443): Read timed out.

    参考链接[侵权删] https://www.jianshu.com/p/3378fa827924 https://yq.aliyun.com/articles/619208 问题描述:在Windows ...

  2. 请问:c语言中d=1/3*3.0;与d=1.0/3*3;d=?有什么区别

    请问:c语言中d=1/33.0;与d=1.0/33;d=?有什么区别 d=1/33.0; 这时d=0,d=(1/3)3.0,这里1是整形,1/3也是整形,等于0,所以03.0=0 d=1.0/33; ...

  3. UnboundLocalError: local variable 'range' referenced before assignment

    1. 报错信息 UnboundLocalError: local variable 'range' referenced before assignment 2. 代码 class Car(): &q ...

  4. python标准库glob 递归目录下所有文件

    import glob for i in glob.glob(r'C:\Desktop\**',recursive=True): print(i) """ re:?*[0 ...

  5. eclipse javase版安装插件开发web项目

    最近学习开发javaweb,但是安装的却是java se版的eclipse,但其无法新建web项目,即找不到Dynamic Web.所以需要下载相应插件.以下为操作过程. 1. 在联网的情况下,打开e ...

  6. Java:LinkedList类小记

    Java:LinkedList类小记 对 Java 中的 LinkedList类,做一个微不足道的小小小小记 概述 java.util.LinkedList 集合数据存储的结构是循环双向链表结构.方便 ...

  7. [对对子队]会议记录4.12(Scrum Meeting 3)

    今天已完成的工作 朱骏豪 ​ 工作内容:找到了游戏的背景场景,用PS扣了按钮的图 ​ 相关issue:实现UI的美术需求 实现游戏场景中的必要模型 梁河览 ​ 工作内容:将关卡选择界面和欢迎界面导入项 ...

  8. 2020BUAA软工个人博客作业-软件案例分析

    2020BUAA软工个人博客作业-软件案例分析 17373010 杜博玮 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人博客作业-软件案例分 ...

  9. NKOJ-4573 Falsita

    问题描述: 到海边了呢...... 如果没有那次选择,现在是不是会好些呢...... 都过去了. 仰望着星空,迎面吹过一阵阵海风,倚靠着护栏,Fine 在海边静静地伫立着,在一个个无际的长夜后,Fin ...

  10. VS2019、Qt5.12及QGis3.16开发常见问题汇总

    在C++.Qt软件开发过程中,常常遇到一些编译错误或警告:本文将VS2019.Qt5.12.10和QGis3.16.10的二次开发过程常见的问题做了整理,供大家参考,也便于日后查阅.该内容分为四部分: ...