51Nod-1610-路径计数

来源:互联网 发布:ubuntu 退出vim 编辑:程序博客网 时间:2024/06/07 12:00

ACM模版

描述

描述

题解

这个题我不会写,看了题解也不怎么会,先 mark 一下吧,给大家提供一下官方题解和一份看起来还不错的代码吧……(╯﹏╰)难受。

描述

我的数学比较差,容斥玩得不是特别好,玩不转,这个 dp 过程大致理解,可是修改操作部分不是特别懂……看了好久也没有理清楚头绪。感觉自己蠢死了~~~

代码

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <cmath>#define clr(a, b) memset(a, b, sizeof(a))using namespace std;typedef long long ll;const int MOD = 1e9 + 7;const int MAXN = 101;const int MAXM = 5e4 + 10;int n, m;int a[MAXM];int b[MAXM];int c[MAXM];int dp[MAXN][MAXN][MAXN];ll tmp[MAXN];ll res[MAXN];ll ans[MAXN];ll dfs(int u, int d){    if (res[u] != -1)    {        return res[u];    }    ll ans = 0;    for (int i = 1; i <= n; i++)    {        if (dp[d][u][i])        {            ans = (ans + dp[d][u][i] + dp[d][u][i] * dfs(i, d)) % MOD;        }    }    return res[u] = ans;}ll cal(int u){    clr(res, -1);    for (int i = 1; i <= n; i++)    {        if (res[i] == -1)        {            dfs(i, u);        }    }    ll ans = 0;    for (int i = 1; i <= n; i++)    {        ans = (ans + res[i]) % MOD;    }    return ans;}int main(){    clr(dp, 0);    cin >> n >> m;    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)            {                dp[j][a[i]][b[i]]++;                if (c[i] / j != j)                {                    dp[c[i] / j][a[i]][b[i]]++;                }            }        }    }    for (int i = 1; i < MAXN; i++)    {        tmp[i] = cal(i);    }    for (int i = MAXN - 1; i > 0; i--)    {        ans[i] = tmp[i];        for (int j = 2 * i; j < MAXN; j += i)        {            ans[i] -= ans[j];        }        ans[i] = (ans[i] % MOD + MOD) % MOD;    }    cout << ans[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)            {                dp[i][a[x]][b[x]]--;                v.push_back(i);                if (c[x] / i != i)                {                    dp[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)            {                dp[i][a[x]][b[x]]++;                v.push_back(i);                if (c[x] / i != i)                {                    dp[c[x] / i][a[x]][b[x]]++;                    v.push_back(c[x] / i);                }            }        }        for (int i = 0; i < v.size(); i++)        {            tmp[v[i]] = cal(v[i]);        }        for (int i = MAXN - 1; i > 0; i--)        {            ans[i] = tmp[i];            for (int j = 2 * i; j < MAXN; j += i)            {                ans[i] -= ans[j];            }            ans[i] = (ans[i] % MOD + MOD) % MOD;        }        cout << ans[1] << endl;    }    return 0;}
原创粉丝点击