首页 > 其他分享 >CF715C Digit Tree

CF715C Digit Tree

时间:2022-08-15 21:36:22浏览次数:58  
标签:Digit int ll Tree rg ans buc CF715C Mod

沝黑。

首先这种统计路径的问题一般联想点分治,然后考虑如何处理经过一个点 \(u\) 的路径。

考虑有一个点 \(p\in u\) 的子树,然后记录路径 \(p\to u\) 和路径 \(u\to p\) 的答案。前者放入一个映射统计,后者存在数组 \(S\) 里面。

最后整体统计,枚举 \(x\in S\),设 \(x\lt M\),统计映射的 \(M-x\) 位置的结果,求一个和。

但是这样可能会有一条路径,从 \(u\) 的一个儿子 \(v\) 的子树来,又到 \(v\) 的子树去。

于是我们考虑分开对每个儿子做一次上述统计子树的算法,然后让 \(u\) 子树的总和减去每个 \(v\) 子树的总和即可。

中间会有把一个多位数和一个数字拼起来的情况,考虑记录下原数的位数,预处理 \(10\) 的次幂以及逆元。

对了,\(M\) 不一定是质数,所以不能用 \(x^{mod-2}\) 的方法求逆元,而是要用 \(\tt exgcd\)。

对了,unordered_map 会被卡,map 已经很够了。

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC target("avx")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")

#include<bits/stdc++.h>
using namespace std;

#ifdef ONLINE_JUDGE
static char buf[1000000],*p1=buf,*p2=buf;
#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++
#endif

inline int read(){
    register int x = 0;
    register char c = getchar();
    for(;c < '0' || c > '9';c = getchar());
    for(;c >= '0' && c <= '9';c = getchar())
        x = x * 10 + (c ^ '0');
    return x;
}

#define rg register
#define il inline

#define rep(i,a,b) for(rg int i = (a);i <= (b);++i)
#define Rep(i,a,b) for(rg int i = (a);i >= (b);--i)

#define pb emplace_back

using ll = long long;

const int N = 1e5 + 5;

int n,val,rt,allsiz,siz[N];
ll sum;
int Mod,inv10,pow10[N],powinv10[N];
bitset<N> vis;
vector<pair<int,int>> G[N];
map<int,long long> buc;
vector<pair<ll,int>> num;

il void exgcd(rg int a,rg int b,rg int &x,rg int &y){
    if(!b) return x = 1,void(y = 0);
    exgcd(b,a % b,y,x);
    y -= a / b * x;
}

il int size(rg int u,rg int ft){
	int res = 1;
	for(auto[v,w] : G[u]) if(!vis[v] && v != ft) res += size(v,u);
	return res;
}

il void fndrt(rg int u,rg int ft){
    int ans = 0; siz[u] = 1;
    for(auto[v,w] : G[u]) if(!vis[v] && v != ft){
        fndrt(v,u);
        siz[u] += siz[v];
        ans = max(ans,siz[v]);
    }
    ans = max(ans,allsiz - siz[u]);
    if(ans < val) val = ans,rt = u;
}

il void dfs(rg int u,rg int ft,rg ll v1,rg ll v2,rg int len){
    if(~len) ++buc[v1],num.pb(v2,len);
    for(auto[v,w] : G[u]) if(v != ft && !vis[v]){
        ll val1 = (1LL * pow10[len + 1] * w % Mod + v1) % Mod;
        ll val2 = (v2 * 10 % Mod + w) % Mod;
        dfs(v,u,val1,val2,len + 1);
    }
}

il ll calc(rg int u,rg int p){
    ll cnt = 0; buc.clear(); num.clear();
    dfs(u,0,p % Mod,p % Mod,p ? 0 : -1);
    for(auto[x,d] : num){
        ll v = (Mod - x) * powinv10[d + 1] % Mod;
        if(buc.find(v) != buc.end()) cnt += buc[v];
        if(!p) cnt += !x;
    }
    if(!p) if(buc.find(0) != buc.end()) cnt += buc[0];
    return cnt;
}

il void solve(rg int u){
    vis[u] = 1;
    sum += calc(u,0);
    for(auto[v,w] : G[u]) if(!vis[v]){
        sum -= calc(v,w);
        allsiz = size(v,0),val = 1e9,rt = 0,fndrt(v,0);
        solve(rt);
    }
}

int main(){
    n = read(),Mod = read();
    rep(i,1,n - 1){
        int u,v,w;
        u = read(),v = read(),w = read();
        ++u,++v;
        G[u].pb(v,w);
        G[v].pb(u,w);
    }
    int x,y; exgcd(10,Mod,x,y);
    inv10 = (x % Mod + Mod) % Mod;
    pow10[0] = powinv10[0] = 1;
    rep(i,1,n) pow10[i] = 10LL * pow10[i - 1] % Mod;
    rep(i,1,n) powinv10[i] = 1LL * inv10 * powinv10[i - 1] % Mod;
    allsiz = n,val = 1e9,rt = 0,fndrt(1,0);
    solve(rt);
    cout << sum << endl;
	return 0;
}

标签:Digit,int,ll,Tree,rg,ans,buc,CF715C,Mod
From: https://www.cnblogs.com/zeno6174/p/CF715C.html

相关文章

  • Balanced Tree (数学函数式子的处理)
    题目大意•求n个点组成的每个节点都满足左右子树大小相差至多1的二叉树个数.•0≤n<264.•关键词:计数2022-暑假-VirtualJudge(vjudge.net)思路:直接用......
  • The following untracked working tree files would be overwritten by checkout
    当使用gitcheckout[branchname]进行分支切换的时候,报了异常:error:Thefollowinguntrackedworkingtreefileswouldbeoverwrittenbycheckout:好多网上推荐......
  • luoguP3521 [POI2011]ROT-Tree Rotations【线段树】
    你要写热,就不能只写热。要写酷暑,写骄阳,写他人耳闻便生恐的炙烤和炎灼。要写白日出门一刻便肤色黝黑,背心透彻。写求雨心切,写出行伞遮。写夜晚不停的风扇和蝉聒。写鸡......
  • K-D Tree
    \(k-DTree\)是一种可以高效处理\(k\)维空间信息的数据结构。在结点数远大于\(k\)时,应用\(k-DTree\)的时间效率很好。——OIWiki对于建树,主流写法是平衡树......
  • hdu7215 Weighted Beautiful Tree
    problem一个点的点权的可能为不变或者变为连着的边的边权。然后dp、dp[u][0]表示变成大于等于w[u]边的最小代价。dp[u][1]表示变成小于等于w[u]边的最小代价。然后对......
  • P2619 [国家集训队]Tree I(K 度限制生成树 二分)
    P2619[国家集训队]TreeI一张\(n\)个点\(m\)条边的带权无向联通图,每条边是黑色或白色。求一棵最小权的恰好有\(need\)条白色边的生成树,题目保证有解。\(n\le5\t......
  • [atAGC025E]Walking on a Tree
    设第$i$条边被$c_{i}$条路径覆盖,显然答案上界为$\sum\min(c_{i},2)$事实上,上界可以被取到,考虑以下构造——取树上的一个叶子,假设其到父亲的边为$i$,对其分类讨论:1.若$c_{......
  • Atcoder Grand Contest 025 E - Walking on a Tree(欧拉回路)
    Atcoder题面传送门打个表发现答案等于每条边被覆盖的次数与\(2\)取min之和,考虑如何构造这个上界。首先考虑树是以\(1\)为中心的菊花图,且任意\(A_i,B_i\ne1\)的......