路径上所有边权的最大公约数定义为一条路径的值。
  给定一个有向无环图。
  T次修改操作,每次修改一条边的边权,每次修改后输出有向无环图上路径的值为1的路径数量(对1,000,000,007取模)。
 Input
  第一行两个整数n和m,分别表示有向无环图上的点数和边数。(1<=n<=100,1<=m<=50,000)
  第2~m+1行每行三个数x,y,z,表示有一条从x到y权值为z的边。(1<=x,y<=n,1<=z<=100)
  第m+2行一个数T,表示修改操作次数(1<=T<=500)。
  接下来T行每行两个数x,y,表示修改第x条边(按照读入的顺序)的边权为y(1<=x<=m,1<=y<=100)。
 Output
  T+1行,修改前和每次修改操作后输出答案。

  朴素的想法...一开始先求出f[i][j]表示在DAG上从i点开始的路径的值为j的方案数,然后每次修改边权的时候,只要求g[i][j]表示从i点开始,经过修改的那条边的路径的值为j的方案数,然后更新f[i][j]就好了(修改就是一次删除一次添加)。

  为了跑得快一点...可以先求出拓扑序、预处理出每个点可以到达哪些点、修改的时候先计算一下有哪些路径值可能被影响...以避免不必要的计算和更新T_T

  复杂度O(100*n*m+T*因子个数*m)大概4亿左右...最后900+ms险过..

  正解是容斥、floyd....其实复杂度和正解也差不多?(常数感人

值为1的路径数量= sum{ 值为x的倍数的路径数量∗u[x] } ,1<=x<=100, u[x] 为莫比乌斯函数。
值为x的倍数的路径数量可以把所有边权为x的倍数的边取出来计算路径条数。
dp[x][i][j]表示只考虑所有边权为x的倍数的边时,点i到点j的路径数量。

初始化的时候,枚举x,然后跑一次floyd即可。
那么删除一条边权为k的倍数的、从x到y的边,可以用如下代码完成:
 for(i=;i<=n;++i)
{
for(j=;j<=n;j++)
{
dp[k][i]][j]-=dp[k][i][x]*dp[k][y][j];
}
}

添加一条边类似,如此便可以做到修改边权的操作。
时间复杂度 O(100∗n^3+T∗因子个数∗n^2) 。

 #include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<bitset>
#define ll long long
#define ui unsigned int
#define ull unsigned long long
#define d double
const int maxn=,mxm=,modd=;
struct zs1{int too,pre,dis;}e[mxm];int tot,last[maxn],x[mxm],y[mxm],val[mxm];
struct zs{int zt,id;}a[maxn];int cnt;
int p[maxn],np,mn[maxn],bel[maxn],zt[maxn];
int dl[maxn],pos[maxn],deg[maxn],too[][maxn];
int f[maxn][],g[maxn][];
int i,j,k,n,m;
char s[maxn]; int ra;char rx;
inline int read(){
rx=getchar(),ra=;
while(rx<''||rx>'')rx=getchar();
while(rx>=''&&rx<='')ra*=,ra+=rx-,rx=getchar();return ra;
} inline void MOD(int &x){if(x>=modd)x-=modd;}
inline void UPD(int &x){if(x<)x+=modd;if(x>=modd)x-=modd;} bool cmpa(zs a,zs b){return a.zt<b.zt;}
inline void prerun(){
a[]=(zs){,};
for(i=;i<=;i++){
for(j=;j<=np;j++)if(!(i%p[j]))break;
if(j>np)p[++np]=i,mn[i]=np;else mn[i]=j;
int tmp=i;
while(tmp>)a[i].zt|=<<(mn[tmp]-),tmp/=p[mn[tmp]];
a[i].id=i;
}
cnt=,a[].zt=-,
std::sort(a+,a++,cmpa);
for(i=;i<=;bel[a[i].id]=cnt,i++)
if(a[i].zt!=a[i-].zt)zt[++cnt]=a[i].zt; for(i=;i<=cnt;i++)for(j=;j<=;j++){
int now=zt[bel[j]],k;
if(i)now&=zt[i];
for(k=;zt[k]!=now;k++);
too[i][j]=k;
}
} inline void insert(int a,int b,int c){e[++tot].too=b,e[tot].dis=c,e[tot].pre=last[a],last[a]=tot;} std::bitset<> con[];
inline void topo(){
int l=,r=,i,j,now,to;
for(i=;i<=n;i++){
con[i][i]=;
if(!deg[i])dl[++r]=i;
}
for(i=;i<=n;i++)f[i][]=;
while(l<r)for(i=last[now=dl[++l]];i;i=e[i].pre){
to=e[i].too,
con[to]|=con[now];
if(!--deg[to])dl[++r]=to;
for(j=;j<=cnt;j++)MOD(f[to][too[j][e[i].dis]]+=f[now][j]);
}
for(i=;i<=n;i++)pos[dl[i]]=i;
} int mp[],id[maxn];
inline void getg(int edge,int fh){
register int i,j,k;
int e_id=bel[val[edge]],e_x=x[edge],e_y=y[edge],e_dis=val[edge];
int num=,now,to;
for(i=;i<=cnt;i++)if((zt[i]&zt[e_id])==zt[i])mp[++num]=i,id[i]=num; memset(g[e_x]+,,num<<);
for(i=;i<=cnt;i++)if(f[e_y][i])MOD(g[e_x][id[too[i][e_dis]]]+=f[e_y][i]);
for(i=pos[e_x]+;i<=n;i++){
if(!con[now=dl[i]][e_y])continue;
for(j=;j<=num;j++)g[now][j]=;
for(j=last[now];j;j=e[j].pre)if(con[(to=e[j].too)][e_x])
for(k=num;k;k--)
MOD(g[now][id[too[mp[k]][e[j].dis]]]+=g[to][k]);
}
for(i=pos[e_x];i<=n;i++)if(con[now=dl[i]][e_x])
for(j=num;j;j--)if(g[now][j])UPD(f[now][mp[j]]+=fh*g[now][j]);
} inline int getans(){
int ans=;for(int i=;i<=n;i++)MOD(ans+=f[i][]);
return ans;
}
int main(){
prerun();
n=read(),m=read();
for(i=;i<=m;i++)
x[i]=read(),y[i]=read(),val[i]=read(),
deg[x[i]]++,insert(y[i],x[i],val[i]);
topo(),printf("%d\n",getans()); int tmp=tot;tot=,memset(last+,,n<<);
for(i=;i<=tmp;i++)insert(x[i],y[i],val[i]); for(int q=read();q;q--){
int edge=read(),v=read();
getg(edge,-),val[edge]=e[edge].dis=v,getg(edge,),printf("%d\n",getans());
}
}

[51nod1610]路径计数的更多相关文章

  1. 51 nod 1610 路径计数(Moblus+dp)

    1610 路径计数 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题   路径上所有边权的最大公约数定义为一条路径的值. 给定一个有向无环图.T次修改操作,每次修改一 ...

  2. 蓝桥杯 历届试题 网络寻路(dfs搜索合法路径计数)

    X 国的一个网络使用若干条线路连接若干个节点.节点间的通信是双向的.某重要数据包,为了安全起见,必须恰好被转发两次到达目的地.该包可能在任意一个节点产生,我们需要知道该网络中一共有多少种不同的转发路径 ...

  3. 堆优化Dijkstra计算最短路+路径计数

    今天考试的时候遇到了一道题需要路径计数,然而蒟蒻从来没有做过,所以在考场上真的一脸懵逼.然后出题人NaVi_Awson说明天考试还会卡SPFA,吓得我赶紧又来学一波堆优化的Dijkstra(之前只会S ...

  4. 【洛谷】P1176: 路径计数2【递推】

    P1176 路径计数2 题目描述 一个N×N的网格,你一开始在(1,1),即左上角.每次只能移动到下方相邻的格子或者右方相邻的格子,问到达(N,N),即右下角有多少种方法. 但是这个问题太简单了,所以 ...

  5. 牛客网 暑期ACM多校训练营(第一场)A.Monotonic Matrix-矩阵转化为格子路径的非降路径计数,Lindström-Gessel-Viennot引理-组合数学

    牛客网暑期ACM多校训练营(第一场) A.Monotonic Matrix 这个题就是给你一个n*m的矩阵,往里面填{0,1,2}这三种数,要求是Ai,j⩽Ai+1,j,Ai,j⩽Ai,j+1 ,问你 ...

  6. 洛谷——P1176 路径计数2

    P1176 路径计数2 题目描述 一个N \times NN×N的网格,你一开始在(1,1)(1,1),即左上角.每次只能移动到下方相邻的格子或者右方相邻的格子,问到达(N,N)(N,N),即右下角有 ...

  7. 洛谷 P1176 路径计数2

    P1176 路径计数2 题目描述 一个N×N的网格,你一开始在(1, 1),即左上角.每次只能移动到下方相邻的格子或者右方相邻的格子,问到达(N, N),即右下角有多少种方法. 但是这个问题太简单了, ...

  8. 【51nod】1776 路径计数

    [51nod]1776 路径计数 我们先把前两种数给排好,排好之后会有\(a + b + 1\)个空隙可以填数,我们计算有\(k\)个空隙两端都是相同字母的方案数 可以用枚举把第二种数分成几段插进去来 ...

  9. HDU 6116 路径计数

    HDU 6116 路径计数 普通生成函数常用于处理组合问题,指数生成函数常用于处理排列问题. 考虑 对于 $ a $ 个 $ A $ 分为很多堆,这么分的方案数是 $ C_{a-1}^{i-1} $ ...

随机推荐

  1. 解决vue.js修改数据无法触发视图

    data:{checkValue:{}}that.checkValue[key] = [] 赋值无法实时改变变量:(数据其实最终被修改,但是并没有触发检测从而更新视图)原因:Vue 不能检测到对象属性 ...

  2. canvas 从初级到XX 2# 让我们在之前的基础之上,再迈进一步吧 [中级向] (上)

    还是老样子,先啰嗦一点前言. 最近各种事务缠身,所以也就隔了比较长的时间才开始码这篇文.希望不会这么快就过气. 好了,接下来就开始码代码.(写到中途,突然感觉到的.本篇设计大量初中物理知识,请怀念的往 ...

  3. xml文件生成方式一(字符串拼接,将多实体类对象写入xml文件)

    1.xml文件生成,拼接字符串使用StringBuffer或StringBuilder 2.拼接好后写入文件即可,将多个实体类写入xml文件 3.这种方式比较简单,但是操作也比较麻烦 4.下面是我的代 ...

  4. ubuntu14.04 解决屏幕亮度无法调节的问题

    sudo gedit /etc/default/grub 在打开文件中找到 GRUB_CMDLINE_LINUX="" 改成 GRUB_CMDLINE_LINUX="ac ...

  5. javascript + sql编写SQL客户端工具tabris

    祝大家2018新年快乐, 前不久发现了一个创意的脚本JtSQL(java编写) 开源地址为:https://github.com/noear/JtSQL JtSQL 特点:*.结合了JS.SQL.模板 ...

  6. Find all factorial numbers less than or equal to N

    A number N is called a factorial number if it is the factorial of a positive integer. For example, t ...

  7. bzoj 4872: [Shoi2017]分手是祝愿

    Description Zeit und Raum trennen dich und mich. 时空将你我分开.B 君在玩一个游戏,这个游戏由 n 个灯和 n 个开关组成,给定这 n 个灯的初始状态 ...

  8. 使用 Kafka 和 ELK 搭建测试日志系统(1)

    本文仅供自己学习,不合适转载. 这是两篇文章的第一部分. 1. 安装 ELK 1.1 安装 ElasticSearch 在海航云上创建一个 Ubutu 16.4 虚机,2核4GB内存. (1)执行以下 ...

  9. Linux目录结构详解

    /: 根目录,一般根目录下只存放目录,不要存放文件,/etc./bin./dev./lib./sbin应该和根目录放置在一个分区中/bin:/usr/bin: 可执行二进制文件的目录,如常用的命令ls ...

  10. 第一本的java 的小总结

    1.Java常见的注释有哪些,语法是怎样的? 1)单行注释用//表示,编译器看到//会忽略该行//后的所文本  2)多行注释/* */表示,编译器看到/*时会搜索接下来的*/,忽略掉/* */之间的文 ...