zoukankan      html  css  js  c++  java
  • [cf715C]Digit Tree

    不断将统计当前这颗子树到之前所有子树的路径并合并,考虑以前的路径为x,当前的路径为y,最终答案即$x\cdot 10^{len(y)}\equiv 0(mod\ p)$,转化为$x\equiv -y/10^{len(y)}(mod\ p)$,对于当前每一个y,查询之前x的个数(用map)即可,注意顺读和逆读的区别。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<map>
     5 using namespace std;
     6 #define ll long long
     7 #define maxN 100001
     8 #define pd (edge[i].to!=fa)&&(!vis[edge[i].to])
     9 map<int,int>mat,mat2;
    10 struct ji{
    11     int nex,to,len;
    12 }edge[maxN<<1];
    13 ll E,n,m,x,y,z,ans,head[maxN],pow[maxN],siz[maxN],ny[maxN];
    14 bool vis[maxN];
    15 void add(int x,int y,int z){
    16     edge[E].nex=head[x];
    17     edge[E].to=y;
    18     edge[E].len=z;
    19     head[x]=E++;
    20 }
    21 ll ksm(ll n,ll t){
    22     if (!t)return 1LL;
    23     ll s=ksm(n,t>>1);
    24     s=s*s%m;
    25     if (t&1)s=s*n%m;
    26     return s;
    27 }
    28 int size(int k,int fa){
    29     siz[k]=1;
    30     for(int i=head[k];i!=-1;i=edge[i].nex)
    31         if (pd)siz[k]+=size(edge[i].to,k);
    32     return siz[k];
    33 }
    34 int query(int k,int fa,int n){
    35     int ma=0,p;
    36     for(int i=head[k];i!=-1;i=edge[i].nex)
    37         if (pd)
    38             if (p=query(edge[i].to,k,n))return p;
    39             else ma=max(1LL*ma,siz[edge[i].to]);
    40     ma=max(1LL*ma,n-siz[k]);
    41     if (ma<=n/2)return k;
    42     return 0;
    43 }
    44 void calc(int k,int fa,int dep,ll s,ll s2){
    45     ans+=mat[(m-s2*ny[++dep]%m)%m]+mat2[s];
    46     for(int i=head[k];i!=-1;i=edge[i].nex)
    47         if (pd)calc(edge[i].to,k,dep,(s+edge[i].len*pow[dep])%m,(s2*10+edge[i].len)%m);
    48 }
    49 void tot(int k,int fa,int dep,ll s,ll s2){
    50     mat[s]++;
    51     mat2[(m-s2*ny[++dep]%m)%m]++;
    52     for(int i=head[k];i!=-1;i=edge[i].nex)
    53         if (pd)tot(edge[i].to,k,dep,(s+edge[i].len*pow[dep])%m,(s2*10+edge[i].len)%m);
    54 }
    55 void dfs(int k,int fa){
    56     int r=query(k,fa,size(k,fa));
    57     mat.clear();
    58     mat2.clear();
    59     mat[0]=mat2[0]=1;
    60     for(int i=head[r];i!=-1;i=edge[i].nex)
    61         if (pd){
    62             calc(edge[i].to,r,0,edge[i].len,edge[i].len);
    63             tot(edge[i].to,r,0,edge[i].len,edge[i].len);
    64         }
    65     vis[r]=true;
    66     for(int i=head[r];i!=-1;i=edge[i].nex)
    67         if (pd)dfs(edge[i].to,r);
    68     vis[r]=false;
    69     mat.clear();
    70     mat2.clear();
    71     mat[0]=mat2[0]=1;
    72     tot(k,fa,0,0,0);
    73     vis[r]=true;
    74 }
    75 int main(){
    76     memset(head,-1,sizeof(head));
    77     scanf("%lld%lld",&n,&m);
    78     for(int i=1;i<n;i++){
    79         scanf("%lld%lld%lld",&x,&y,&z);
    80         z%=m;
    81         add(++x,++y,z);
    82         add(y,x,z);
    83     }
    84     x=y=m;
    85     for(int i=2;1LL*i*i<=m;i++)
    86         if (y%i==0){
    87             x=x/i*(i-1);
    88             while (y%i==0)y/=i;
    89         }
    90     if (y>1)x=x/y*(y-1);
    91     for(int i=0;i<=n;i++)pow[i]=ksm(10,i);
    92     for(int i=0;i<=n;i++)ny[i]=ksm(pow[i],x-1);
    93     dfs(1,0);
    94     printf("%lld",ans);
    95 }
    View Code
  • 相关阅读:
    C# 使用Enumerable.Range 打印数字
    C#中的范围类型(Range Type)
    C# 编程中的堆栈(Stack)和队列(Queue)
    C# 委托(delegate、Action、Func、predicate)
    使用线程以及对信号量 AutoResetEvent和ManualResetEvent的理解
    SQL Sever触发器的基本语法与作用
    C#控制台程序使用Log4net日志组件
    初级委托详解(C# 用委托有什么好处? 它起什么作用?)
    獲取串口數據,設置串口
    MVC 下 打包多个word到压缩包
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11254619.html
Copyright © 2011-2022 走看看