Codeforces 1051E Vasya and Big Integers&1051F The Shortest Statement
1051E. Vasya and Big Integers
题意
给出三个大整数\(a,l,r\),定义\(a\)的一种合法的拆分为把\(a\)表示成若干个字符串首位相连,且每个字符串的大小在\(l,r\)之间,求每个字符串不能有前导零,求\(a\)有多少种合法的拆分方案。
题解
不难想到\(dp\),设\(dp_i\)表示前\(i\)个数有多少种合法的拆分方案。
\(dp_i=\sum_{j=1}^i dp_{j-1}\)(从\(j+1~i\)拆分的数在\(l,r\)之间)
直接转移是\(O(n^2)\),因为如果新拆分的数的长度小于\(l\)的长度,或者大于\(r\)的长度的话,那肯定是不合法的,所以我们考虑把转移分成三种。
1.新拆分的数的长度等于\(l\)的长度。
2.新拆分的数的长度等于\(r\)的长度。
3.新拆分的数的长度在\([l+1,r-1]\)这个区间里。
对于第三种,随便开个变量xjb维护下就行了。
对于前两种,问题就转换成了比较两个串的字典序。
比较两个字符串字典序的大小,就是相当于比较两个串\(lcp\)的后一位字符的大小。
\(lcp\)?我一眼\(SA\),经机房大佬提醒,突然想到可以写\(hash\)+二分减少代码量其实是太久没写SA忘了SA怎么写了,然后就被卡自然溢出到怀疑人生。
\(cf\)上一定不能写自然溢出!\(cf\)上一定不能写自然溢出!
#include<bits/stdc++.h>
#define For(i,x,y) for (register int i=(x);i<=(y);i++)
#define Dow(i,x,y) for (register int i=(x);i>=(y);i--)
#define cross(i,k) for (register int i=first[k];i;i=last[i])
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
inline ll read(){
ll x=0;int ch=getchar(),f=1;
while (!isdigit(ch)&&(ch!='-')&&(ch!=EOF)) ch=getchar();
if (ch=='-'){f=-1;ch=getchar();}
while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int N = 1e6+10;
int na,nl,nr;
char a[N],l[N],r[N];
inline void rd(){
scanf("%s%s%s",a+1,l+1,r+1);
na=strlen(a+1),nl=strlen(l+1),nr=strlen(r+1);
}
const ull base = 2333;
const ll mod = 998244353;
ull p[N],hashl[N],hashr[N],hasha[N];
ll P[N],Hashl[N],Hashr[N],Hasha[N];
inline void init(){
p[0]=1;
For(i,1,na) p[i]=p[i-1]*base;
For(i,1,nl) hashl[i]=hashl[i-1]*base+l[i];
For(i,1,nr) hashr[i]=hashr[i-1]*base+r[i];
For(i,1,na) hasha[i]=hasha[i-1]*base+a[i];
P[0]=1;
For(i,1,na) P[i]=P[i-1]*base%mod;
For(i,1,nl) Hashl[i]=(Hashl[i-1]*base+l[i])%mod;
For(i,1,nr) Hashr[i]=(Hashr[i-1]*base+r[i])%mod;
For(i,1,na) Hasha[i]=(Hasha[i-1]*base+a[i])%mod;
}
inline ull Queryl(int x){return hashl[x];}
inline ull queryl(int x){return Hashl[x];}
inline ull Queryr(int x){return hashr[x];}
inline ull queryr(int x){return Hashr[x];}
inline ull Querya(int l,int r){return hasha[r]-hasha[l-1]*p[r-l+1];}
inline ull querya(int l,int r){return (Hasha[r]-Hasha[l-1]*P[r-l+1]%mod+mod)%mod;}
ll sum,dp[N];
inline void Mod(ll &x){for (;x>=mod;x-=mod);}
inline bool checkl(int x){
if (a[x]=='0'&&nl>1) return 0;
int L=1,R=nl,mid,ans=0;
while (L<=R) mid=L+R>>1,(Queryl(mid)==Querya(x,x+mid-1)&&queryl(mid)==querya(x,x+mid-1))?(ans=mid,L=mid+1):R=mid-1;
return (ans==nl)?1:(a[x+ans]>l[ans+1]);
}
inline bool checkr(int x){
if (a[x]=='0'&&nr>1) return 0;
int L=1,R=nr,mid,ans=0;
while (L<=R) mid=L+R>>1,(Queryr(mid)==Querya(x,x+mid-1)&&queryr(mid)==querya(x,x+mid-1))?(ans=mid,L=mid+1):R=mid-1;
return (ans==nr)?1:(a[x+ans]<r[ans+1]);
}
inline void solve(){
dp[0]=1,a[0]='0';
For(i,nl,na){
if (a[i-nl]!='0'&&nr-nl>1) Mod(sum+=dp[i-nl-1]);
if (i-nr+1>0&&a[i-nr+1]!='0'&&nr-nl>1) Mod(sum=sum+mod-dp[i-nr]);
dp[i]=sum;//printf("%d %lld\n",i,sum);
if (nl==nr) Mod(dp[i]+=checkl(i-nl+1)*checkr(i-nr+1)*dp[i-nl]);
else {
Mod(dp[i]+=checkl(i-nl+1)*dp[i-nl]);
if (i-nr+1>0) Mod(dp[i]+=checkr(i-nr+1)*dp[i-nr]);
}
}
printf("%lld",dp[na]);
}
int main(){
rd(),init(),solve();
}
1051F. The Shortest Statement
题意
给出一个无向连通图,给出\(q\)次询问,每次询问\(u->v\)的最短路,边数-点数<=20。
题解
看到联通,边数-点数<=20,一眼想到肯定是把这个图转成几棵树然后求两个在所有树上的距离的\(min\)。
图怎么转成树?还要最短路?\(Dij\)的拓展好像就是一棵树来着。
凭感觉做题.jpg
首先我们先随便搞个点作为起点跑\(Dij\),两个点的最短路如果不是两个点在树上的距离的话,那肯定是就经过了一条非树边,所以我们把所有的非树边都抠出来,然后对非树边的结点为起点,再跑\(Dij\)建树。
最多非树边只会有\(21\)条,所以复杂度\(O(nlogn*21)\)
#include<bits/stdc++.h>
#define For(i,x,y) for (register int i=(x);i<=(y);i++)
#define Dow(i,x,y) for (register int i=(x);i>=(y);i--)
#define cross(i,k) for (register int i=first[k];i;i=last[i])
#define Cross(i,k) for (register int i=First[k];i;i=Last[i])
using namespace std;
typedef long long ll;
inline ll read(){
ll x=0;int ch=getchar(),f=1;
while (!isdigit(ch)&&(ch!='-')&&(ch!=EOF)) ch=getchar();
if (ch=='-'){f=-1;ch=getchar();}
while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int N = 1e5+10;
int n,m,x,y,z;
int tot,first[N],last[N<<1],to[N<<1];
ll val[N<<1];
inline void Add(int x,int y,int z){to[++tot]=y,val[tot]=z,last[tot]=first[x],first[x]=tot;}
int Tot,First[N],Last[N],To[N];
ll Val[N];
inline void add(int x,int y,int z){To[++Tot]=y,Val[Tot]=z,Last[Tot]=First[x],First[x]=Tot;}
int cnt,rt[50];
bool vis[N];
inline void GetRt(int u,int fa){
vis[u]=1;
cross(i,u){
int v=to[i];
if (v==fa) continue;
if (vis[v]){rt[++cnt]=u;continue;}
}
Cross(i,u) if (To[i]!=fa) GetRt(To[i],u);
}
struct Tree{
int rt;
int size[N],son[N],dep[N],fa[N];
ll dis[N];
inline void dfs(int u){
size[u]=1,dep[u]=dep[fa[u]]+1;
Cross(i,u){
int v=To[i];
if (v==fa[u]) continue;
fa[v]=u,dis[v]=dis[u]+Val[i],dfs(v),size[u]+=size[v];
if (size[v]>size[son[u]]) son[u]=v;
}
}
int top[N];
inline void dfs(int u,int Top){
top[u]=Top;
if (son[u]) dfs(son[u],Top);
Cross(i,u) if (To[i]!=fa[u]&&To[i]!=son[u]) dfs(To[i],To[i]);
}
inline int LCA(int x,int y){
for (;top[x]!=top[y];dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]]);
return dep[x]<dep[y]?x:y;
}
inline void Build(){dfs(rt),dfs(rt,rt);}
inline ll Query(int x,int y){return dis[x]+dis[y]-dis[LCA(x,y)]*2;}
}t[50];
struct node{
int u;ll val;
inline bool operator < (const node &b)const{return val>b.val;}
};
priority_queue<node>q;
int fa[N];
ll dis[N],FaVal[N];
inline void Dij(int k,int s){
For(i,1,n) dis[i]=1e18,vis[i]=0;
dis[s]=fa[s]=0,q.push((node){s,0});
while (!q.empty()){
int u=q.top().u;q.pop();
if (vis[u]) continue;vis[u]=1;
cross(i,u){
int v=to[i];
if (dis[u]+val[i]<dis[v]) dis[v]=dis[u]+val[i],q.push((node){v,dis[v]}),fa[v]=u,FaVal[v]=val[i];
}
}
Tot=0,memset(First,0,sizeof First);
//printf("rt=%d ",s);For(i,1,n) printf("%d ",fa[i]);puts("");
For(i,1,n) if (fa[i]) add(fa[i],i,FaVal[i]);
t[k].rt=s,t[k].Build();
}
inline void Build(){For(i,1,cnt) Dij(i,rt[i]);}
int main(){
//freopen("data.in","r",stdin);
//freopen("m.out","w",stdout);
n=read(),m=read();
For(i,1,m) x=read(),y=read(),z=read(),Add(x,y,z),Add(y,x,z);
//puts("");
//rt[cnt=1]=1,GetRt(1,0),Build();
rt[cnt=1],Dij(1,1),memset(vis,0,sizeof vis),GetRt(1,0),Build();
//printf("rt:");For(i,1,cnt) printf("%d ",rt[i]);puts("");
int q=read();
while (q--){
x=read(),y=read();ll ans=1e18;
For(i,1,cnt) ans=min(ans,t[i].Query(x,y));
printf("%lld\n",ans);
}
}
/*
10 10
1 2 9
2 3 5
3 4 5
3 5 8
4 6 6
3 7 6
7 8 8
8 9 4
3 10 4
8 1 7
1
9 5
*/
Codeforces 1051E Vasya and Big Integers&1051F The Shortest Statement的更多相关文章
- Codeforces 1051E. Vasya and Big Integers
题意:给你N个点M条边,M-N<=20,有1e5个询问,询问两点的最短距离.保证没有自环和重边. 题解:连题目都在提示你这个20很有用,所以如果是颗树的话那任意两点的最短距离就是求一下lca搞一 ...
- codeforces 1051F The Shortest Statement
题目链接:codeforces 1051F The Shortest Statement 题意:\(q\)组询问,求任意两点之间的最短路,图满足\(m-n\leq 20\) 分析:一开始看这道题:fl ...
- [Codeforces 1051F] The Shortest Statement 解题报告(树+最短路)
题目链接: https://codeforces.com/contest/1051/problem/F 题目大意: 给出一张$n$个点,$m$条边的带权无向图,多次询问,每次给出$u,v$,要求输出$ ...
- Codeforces.1051F.The Shortest Statement(最短路Dijkstra)
题目链接 先随便建一棵树. 如果两个点(u,v)不经过非树边,它们的dis可以直接算. 如果两个点经过非树边呢?即它们一定要经过该边的两个端点,可以直接用这两个点到 u,v 的最短路更新答案. 所以枚 ...
- 2018.09.24 codeforces 1051F. The Shortest Statement(dijkstra+lca)
传送门 这真是一道一言难尽的题. 首先比赛的时候居然没想出来正解. 其次赛后调试一直调不出来最后发现是depth传错了. 其实这是一道简单题啊. 对于树边直接lca求距离. 由于非树边最多21条. 因 ...
- Educational Codeforces Round 51 (Rated for Div. 2) The Shortest Statement
题目链接:The Shortest Statement 今天又在群里看到一个同学问$n$个$n$条边,怎么查询两点直接最短路.看来这种题还挺常见的. 为什么最终答案要从42个点的最短路(到$x,y$) ...
- The Shortest Statement CodeForces - 1051F(待测试)
#include <iostream> #include <cstdio> #include <sstream> #include <cstring> ...
- CodeForces - 837E - Vasya's Function | Educational Codeforces Round 26
/* CodeForces - 837E - Vasya's Function [ 数论 ] | Educational Codeforces Round 26 题意: f(a, 0) = 0; f( ...
- CodeForces - 1051E :Vasya and Big Integers(Z算法 & DP )
题意:给定字符串S,A,B.现在让你对S进行切割,使得每个切割出来的部分在[A,B]范围内,问方案数. 思路:有方程,dp[i]=Σ dp[j] (S[j+1,i]在合法范围内). 假设M和 ...
随机推荐
- 关于linux的一些基础知识
一.基础 1.linux所有内容以文件形式保存,包括硬件. 2.linux 不区分扩展名,靠权限区分. #但是,约定 .sh脚本文件 .conf配置文件. 3.-rw-r--r-- ...
- 根据 plist 还原 图片
1. python 环境自己配置(支持windows Mac ) 2. 把所有的 plist 和 大图片放到一个目录下 3.如果添加了 系统环境变量 就直接双击运行脚本,如果没有设置,把脚本拽到DO ...
- C#里面中将字符串转为变量名
public partial class Form1 : Form { string str = "spp"; public string spp = "very goo ...
- 利用Jsoup模拟跳过登录爬虫获取数据
今天在学习爬虫的时候想着学习一下利用jsoup模拟登录.下面分为有验证码和无验证码的情况进行讨论. ---------------------------无验证码的情况---------------- ...
- Mysql中的primary key 与auto_increment
mysql> create table cc(id int auto_increment); ERROR (): Incorrect table definition; there can be ...
- MAC 文件被锁定
从windows拷贝到MAC的文件,有时候会被锁定.右键-简介-已锁定也是灰色的,无法取消: xattr -l 文件名 xattr -d com.apple.FinderInfo 文件名
- Ubuntu vi 上下左右变ABCD问题解决方法
---恢复内容开始--- 错误问题:vi上下左右键显示为ABCD的问题 解决方法: 只要依次执行以下两个命令即可完美解决Ubuntu下vi编辑器方向键变字母的问题. 一.执行命令 sudo apt-g ...
- spring集成swagger
随着互联网技术的发展,现在的网站架构基本都由原来的后端渲染,变成了:前端渲染.前后端分离的形态,而且前端技术和后端技术在各自的道路上越走越远. 前端和后端的唯一联系,变成了API接口:API文档变成了 ...
- (一) Mysql 简介及安装和配置
第一节:Mysql 简介 百度百科 第二节:Mysql 安装及配置 1,Mysql5.1 下载及安装 2,Mysql 数据库编码配置 utf-8 3,Mysql 图形界面 Sqlyog 下载及安装
- PHP–图像XX因其本身有错无法显示
1.你输出的图像格式 PHP不支持,检查GD库有没有开启 对应的图像格式是不是支持2.文件里面的格式是否一致 如果是UTF-8的检查文件格式是不是UTF-8 [UTF-8+BOM很多IDE默认是这个格 ...