51nod 1610 路径计数(容斥+dp)

原创 2016年08月31日 11:23:02

路径计数
System Message (命题人)
基准时间限制:1 秒 空间限制:131072 KB 分值: 80
路径上所有边权的最大公约数定义为一条路径的值。
给定一个有向无环图。
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行,修改前和每次修改操作后输出答案。
Input示例
4 4
1 2 2
2 4 3
1 3 4
3 4 2
4
1 5
2 10
3 3
4 6
Output示例
1
1
0
1
0


gcd=1gcd1100100
gcdO(100n2)
500GG
gcd3gcd=2
mat[k][i][j]kij
i
i

O(Tvn2)O(Tsqrt(v)n2)


代码:

#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#pragma comment(linker,"/STACK:102400000,102400000")

using namespace std;
#define   MAX           100005
#define   MAXN          1000005
#define   maxnode       205
#define   sigma_size    2
#define   lson          l,m,rt<<1
#define   rson          m+1,r,rt<<1|1
#define   lrt           rt<<1
#define   rrt           rt<<1|1
#define   middle        int m=(r+l)>>1
#define   LL            long long
#define   ull           unsigned long long
#define   mem(x,v)      memset(x,v,sizeof(x))
#define   lowbit(x)     (x&-x)
#define   pii           pair<int,int>
#define   bits(a)       __builtin_popcount(a)
#define   mk            make_pair
#define   limit         10000

//const int    prime = 999983;
const int    INF   = 0x3f3f3f3f;
const LL     INFF  = 0x3f3f;
//const double pi    = acos(-1.0);
const double inf   = 1e18;
//const double eps   = 1e-9;
const LL     mod   = 1e9+7;
const ull    mx    = 133333331;

/*****************************************************/
inline void RI(int &x) {
      char c;
      while((c=getchar())<'0' || c>'9');
      x=c-'0';
      while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
 }
/*****************************************************/

LL dp[105];
int a[50005],b[50005],c[50005];
int mat[105][105][105];
LL g[105];
LL f[105];
int n;

LL dfs(int u,int d){
    if(dp[u]!=-1) return dp[u];
    LL ans=0;
    for(int i=1;i<=n;i++){
        if(mat[d][u][i]){
            ans=(ans+mat[d][u][i]+mat[d][u][i]*dfs(i,d))%mod;
        }
    }
    return dp[u]=ans;
}
LL cal(int u){
    mem(dp,-1);
    for(int i=1;i<=n;i++){
        if(dp[i]==-1) dfs(i,u);
    }
    LL ans=0;
    for(int i=1;i<=n;i++) ans=(ans+dp[i])%mod;
    return ans;
}
int main(){
    //freopen("in.txt","r",stdin);
    int m;
    cin>>n>>m;
    mem(mat,0);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&a[i],&b[i],&c[i]);
        for(int j=1;j*j<=c[i];j++){
            if(c[i]%j==0){
                mat[j][a[i]][b[i]]++;
                if(c[i]/j!=j) mat[c[i]/j][a[i]][b[i]]++;
            }
        }
    }
    for(int i=1;i<=100;i++) g[i]=cal(i);
    for(int i=100;i>0;i--){
        f[i]=g[i];
        for(int j=2*i;j<=100;j+=i){
            f[i]-=f[j];
        }
        f[i]=(f[i]%mod+mod)%mod;
    }
    cout<<f[1]<<endl;
    int t;
    cin>>t;
    while(t--){
        int x,y;
        scanf("%d%d",&x,&y);
        vector<int> v;
        for(int i=1;i*i<=c[x];i++){
            if(c[x]%i==0){
                mat[i][a[x]][b[x]]--;
                v.push_back(i);
                if(c[x]/i!=i) mat[c[x]/i][a[x]][b[x]]--,v.push_back(c[x]/i);
            }
        }
        c[x]=y;
        for(int i=1;i*i<=c[x];i++){
            if(c[x]%i==0){
                mat[i][a[x]][b[x]]++;
                v.push_back(i);
                if(c[x]/i!=i) mat[c[x]/i][a[x]][b[x]]++,v.push_back(c[x]/i);
            }
        }
        for(int i=0;i<v.size();i++){
            g[v[i]]=cal(v[i]);
        }
        for(int i=100;i>0;i--){
            f[i]=g[i];
            for(int j=2*i;j<=100;j+=i){
                f[i]-=f[j];
            }
            f[i]=(f[i]%mod+mod)%mod;
        }
        cout<<f[1]<<endl;
    }
    return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

【51Nod 1610】路径计数

Description路径上所有边权的最大公约数定义为一条路径的值。 给定一个有向无环图。 T次修改操作,每次修改一条边的边权,每次修改后输出有向无环图上路径的值为1的路径数量(对1,000,00...

《MS SQL Server2005 技术内幕—T-SQL查询》读书笔记一:SQL逻辑查询处理

转自:http://blog.csdn.net/yinyuan1987/archive/2011/03/31/6290674.aspxhttp://www.joyoustore.com  自己看书的一...

【51Nod 1610】路径计数

Description路径上所有边权的最大公约数定义为一条路径的值。 给定一个有向无环图。 T次修改操作,每次修改一条边的边权,每次修改后输出有向无环图上路径的值为1的路径数量(对1,000,00...

NOIP2017模拟赛(7) 总结

前言:第一题想复杂了,第二题犯了一个sb错误,第三题的话。。。a 斯诺克题目描述考虑这样一个斯诺克球台,它只有四个袋口,分别在四个角上(如下图所示)。我们把所有桌子边界上的整数点作为击球点(除了4个袋...
  • Ab_Ever
  • Ab_Ever
  • 2017年06月22日 14:02
  • 439

51Nod-1610-路径计数

ACM模版描述题解这个题我不会写,看了题解也不怎么会,先 markmark 一下吧,给大家提供一下官方题解和一份看起来还不错的代码吧……(╯﹏╰)难受。我的数学比较差,容斥玩得不是特别好,玩不转,这个...
  • f_zyj
  • f_zyj
  • 2017年08月04日 23:45
  • 294

51nod 1610 路径计数

因为是无环图,所以可以用记忆化搜索做。 可以根据公约数,将图拆成100个子图。 由于有重复,所以再加上容斥。 #include using namespace std; const long ...
  • xin_jun
  • xin_jun
  • 2017年07月23日 16:23
  • 70

【51nod1597】【DP】有限背包计数问题

Description 你有一个大小为n的背包,你有n种物品,第i种物品的大小为i,且有i个,求装满这个背包的方案数有多少 两种方案不同当且仅当存在至少一个数i满足第i种物品使用的数量...

[背包DP || 多项式] 51Nod 1597 有限背包计数问题

这是个多重背包 直接做肯定接受不了时间复杂度 我们看当体积大于 n√\sqrt n 时 是用不完的 是个完全背包 但还是接受不了复杂度 再观察 体积大的总共只可能取n√\sqrt n个 令fi,...

51Nod 算法马拉松17 路径计数 莫比乌斯函数加暴力构图

题目大意现在定义路径上所有边权的最大公约数定义为一条路径的值。 现在给定一个NN个点MM条边有向无环图。进行TT次修改操作,每次修改一条边的边权,每次修改后输出有向无环图上路径的值为1的路径数量(对...

51nod1835 完全图 容斥+dp

Description初始有n个点,任意两个点之间有一条无向边,现在要移除一些无向边(至少一条),问移除后有恰好m个连通块的方案数是多少。 两个方案不同当且仅当存在至少一条无向边在某个方案中被移除,...
  • jpwang8
  • jpwang8
  • 2017年11月29日 17:18
  • 60
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:51nod 1610 路径计数(容斥+dp)
举报原因:
原因补充:

(最多只允许输入30个字)