zoukankan      html  css  js  c++  java
  • [hdu4812]D Tree(点分治)

    题意:问有多少条路径,符合路径上所有节点的权值乘积模1000003等于k。

    解题关键:预处理阶乘逆元,然后通过hash和树形dp$O(1)$的判定乘积存在问题,注意此道题是如何处理路径保证不重复的,具有启发意义。

    代码:2340ms,这段代码最重要的可取点就是如何通过操作省去memset的过程

    复杂度:$O(nlog n)$

      1 #pragma comment(linker,"/STACK:102400000,102400000")
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cstdlib>
      6 #include<iostream>
      7 #include<cmath>
      8 #define maxn 100040
      9 #define maxm 1000500
     10 using namespace std;
     11 typedef long long ll;
     12 const ll mod=1000003;
     13 const ll inf=1ll<<60;
     14 ll n,k,ans,size,s[maxn],f[maxn],path[maxn],cr,val[maxn],inv[maxm],ansl,ansr;
     15 ll head[maxn],cnt,root,pathid[maxn],flag[maxm],mp[maxm],ca;
     16 bool vis[maxn];
     17 struct edge{
     18     ll to,nxt;
     19 }e[maxn<<1];
     20 
     21 void add_edge(ll u,ll v){
     22     e[cnt].to=v;
     23     e[cnt].nxt=head[u];
     24     head[u]=cnt++;
     25 }
     26 
     27 inline ll read(){
     28     char k=0;char ls;ls=getchar();for(;ls<'0'||ls>'9';k=ls,ls=getchar());
     29     ll x=0;for(;ls>='0'&&ls<='9';ls=getchar())x=(x<<3)+(x<<1)+ls-'0';
     30     if(k=='-')x=0-x;return x;
     31 }
     32 
     33 void get_root(ll u,ll fa){//get_root会用到size
     34     s[u]=1;f[u]=0;//f是dp数组
     35     for(ll i=head[u];i!=-1;i=e[i].nxt){
     36         ll v=e[i].to;
     37         if(v==fa||vis[v]) continue;
     38         get_root(v,u);
     39         s[u]+=s[v];
     40         f[u]=max(f[u],s[v]);
     41     }
     42     f[u]=max(f[u],size-s[u]);
     43     root=f[root]>f[u]?u:root;
     44 }
     45 
     46 void get_path_size(ll u,ll fa,ll dis){//同时获取size和depth,size是深度,depth是dis的意思
     47     path[cr]=dis%mod*val[u]%mod;
     48     pathid[cr]=u;
     49     cr++;
     50     s[u]=1;
     51     ll tm=path[cr-1]%mod;
     52     for(ll i=head[u];i!=-1;i=e[i].nxt){
     53         ll v=e[i].to;
     54         if(v==fa||vis[v]) continue;
     55         get_path_size(v,u,tm);
     56         s[u]+=s[v];
     57     }
     58 }
     59 
     60 void getans(ll a,ll b){
     61     if(a>b) swap(a,b);
     62     if(ansl>a) ansl=a,ansr=b;
     63     else if(ansl==a&&ansr>b) ansr=b;
     64 }
     65 
     66 void work(ll u,ll fa){
     67     vis[u]=true;
     68     for(ll i=head[u];i!=-1;i=e[i].nxt){
     69         ll v=e[i].to;
     70         if(v==fa||vis[v]) continue;
     71         cr=0;
     72         get_path_size(v,u,1);
     73         for(ll j=0;j<cr;j++){
     74             if(path[j]*val[u]%mod==k) getans(pathid[j],u);
     75             ll tm=k*inv[path[j]*val[u]%mod]%mod;
     76             if(flag[tm]!=ca) continue;
     77             getans(mp[tm],pathid[j]);
     78         }
     79         for(int j=0;j<cr;j++){
     80             ll tm=path[j];
     81             if(flag[tm]!=ca||mp[tm]>pathid[j]) flag[tm]=ca,mp[tm]=pathid[j];
     82         }
     83     }
     84     ca++;
     85     for(ll i=head[u];i!=-1;i=e[i].nxt){
     86         ll v=e[i].to;
     87         if(vis[v]||v==fa) continue;
     88         size=s[v],root=0;
     89         get_root(v,u);
     90         work(root,u);
     91     }
     92    // vis[u]=false;
     93 }
     94 
     95 void init(){
     96     memset(vis,0,sizeof vis);
     97     memset(head,-1,sizeof head);
     98     //memset(flag,0,sizeof flag);
     99     ans=cnt=0;
    100     //ca=1;
    101 }
    102 
    103 ll mod_pow(ll x,ll n,ll p){
    104     ll res=1;
    105     while(n){
    106         if(n&1) res=res*x%p;
    107         x=x*x%p;
    108         n>>=1;
    109     }
    110     return res;
    111 }
    112 
    113 int main(){
    114     ll a,b;
    115     f[0]=inf;inv[0]=1;
    116     for(ll i=1;i<1000003;i++) inv[i]=mod_pow(i,mod-2,mod);
    117     ca=0;
    118     while(scanf("%lld%lld",&n,&k)!=EOF){
    119         ca++;
    120         init();
    121         for(int i=1;i<=n;i++) val[i]=read()%mod;
    122         for(int i=0;i<n-1;i++){
    123             a=read(),b=read();
    124             add_edge(a,b);
    125             add_edge(b,a);
    126         }
    127         size=n,root=0;
    128         get_root(1,-1);
    129         ansl=ansr=inf;
    130         work(root,-1);
    131         if(ansl==inf) printf("No solution
    ");
    132         else printf("%lld %lld
    ",ansl,ansr);
    133     }
    134     return 0;
    135 }
    136  
  • 相关阅读:
    UICollectionView中使用 UICollectionViewFlowLayout进行布局(模仿苹果相册)
    使用CocoaPods被卡住:Updating local specs repositories
    【原】iOS 同时重写setter和getter时候报错:Use of undeclared identifier '_name';did you mean 'name'
    iOS 设置不同的字体颜色
    使用java代码,动态给TextView设置drawable
    格式化浮点数(保留指定位数)
    监听输入法的出现和隐藏
    dp和px的转换
    获取状态栏高度
    获取在attr.xml中声明的主题样式
  • 原文地址:https://www.cnblogs.com/elpsycongroo/p/7495983.html
Copyright © 2011-2022 走看看