标签:i++ ash work algo 多少 hid lld printf struct
题意:问有多少条路径,符合路径上所有节点的权值乘积模1000003等于k。
解题关键:预处理阶乘逆元,然后通过hash和树形dp$O(1)$的判定乘积存在问题,注意此道题是如何处理路径保证不重复的,具有启发意义。
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 } 93 94 void init(){ 95 memset(vis,0,sizeof vis); 96 memset(head,-1,sizeof head); 97 memset(flag,0,sizeof flag); 98 ans=cnt=0; 99 ca=1; 100 } 101 102 ll mod_pow(ll x,ll n,ll p){ 103 ll res=1; 104 while(n){ 105 if(n&1) res=res*x%p; 106 x=x*x%p; 107 n>>=1; 108 } 109 return res; 110 } 111 112 int main(){ 113 ll a,b; 114 f[0]=inf;inv[0]=1; 115 for(ll i=1;i<1000003;i++) inv[i]=mod_pow(i,mod-2,mod); 116 while(scanf("%lld%lld",&n,&k)!=EOF){ 117 init(); 118 for(int i=1;i<=n;i++) val[i]=read()%mod; 119 for(int i=0;i<n-1;i++){ 120 a=read(),b=read(); 121 add_edge(a,b); 122 add_edge(b,a); 123 } 124 size=n,root=0; 125 get_root(1,-1); 126 ansl=ansr=inf; 127 work(root,-1); 128 if(ansl==inf) printf("No solution\n"); 129 else printf("%lld %lld\n",ansl,ansr); 130 } 131 return 0; 132 }
标签:i++ ash work algo 多少 hid lld printf struct
原文地址:http://www.cnblogs.com/elpsycongroo/p/7495983.html