20180629小测

T1:


这不是树形背包水题吗?只是数据范围略大,注意常数。
(话说即使时间咕成NOIP,也不能放NOIP题啊)
代码:

 1 #pragma GCC optimize("Ofast","no-stack-protector")
 2 //#pragma GCC target("avx2")
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cctype>
 7 typedef long long int lli;
 8 const int maxn=4e3+1e2;
 9 
10 int lson[maxn],rson[maxn],c[maxn],siz[maxn];
11 lli f[maxn][maxn];
12 bool vis[maxn];
13 
14 inline void dfs(int pos) {
15     if( !lson[pos] && !rson[pos] ) { // a leaf node .
16         f[pos][0] = 0 , f[pos][1] = c[pos] , siz[pos] = 1;
17         return;
18     }
19     dfs(lson[pos]) , dfs(rson[pos]) , memset(f[pos],0x3f,(siz[lson[pos]]+siz[rson[pos]]+1)<<3);
20     for(int i=0;i<=siz[lson[pos]];i++) for(int j=0;j<=siz[rson[pos]];j++) f[pos][i+j] = std::min( f[pos][i+j] , f[lson[pos]][i] + f[rson[pos]][j] + (lli) ( i ^ j ) * c[pos] );
21     siz[pos] = siz[lson[pos]] + siz[rson[pos]];
22 }
23 
24 inline int getint() {
25     int ret = 0 , ch;
26     while( !isdigit(ch=getchar()) );
27     do ret = ret * 10 + ch - '0'; while( isdigit(ch=getchar()) );
28     return ret;
29 }
30 
31 int main() {
32     static int t,n,root;
33     t = getint();
34     while(t--) {
35         n = getint() , memset(vis,0,sizeof(vis));
36         for(int i=1;i<=n;i++) vis[lson[i] = getint()] = 1 , vis[rson[i] = getint()] = 1;
37         for(int i=1;i<=n;i++) c[i] = getint();
38         for(int i=1;i<=n;i++) if( !vis[i] ) root = i;
39         dfs(root);
40         for(int i=1;i<=siz[root];i++) printf("%lld%c",f[root][i],i!=siz[root]?' ':'\n');
41     }
42     return 0;
43 }
View Code

 


T2:


组合数学神题!考虑第一种用多少个,则答案就是C(n,i)*C(m,t-i)*C(t,i)。
好的,我会lucas定理,我能写暴力!(阻止我AK的题都不是好题.jpg)
(然而暴力的后15分由于n太大数据组数太多,根本没有实装,于是只有5分QAQ)
正解考虑lucas定理,显然我们在lucas定理的每一位都不能进位,同时n和m在每一位选择的值都不能超过t(否则组合数为0)。
所以我们令f[i][j]表示考虑最大的i层,第一种选择的数mod p=j的方案数。
转移的话,首先凑出每层自己的方案,如果n在这层的数值为n1,m为m1,t为t1,在这层选择第一种的数量为i,则g[level][i%p] += C(n1,i) * C(m1,t1-i) * C(t1,i)。(这里的g为只考虑一层的方案数)
然后考虑层与层间的结合,显然转移为f[level][(i*mod+j)%p] += f[level-1][i] * g[level][j]。变换一下下标显然是个卷积,FFT优化即可。
(怎么FFT?其实随便找一个大于mod*p的数作为模数,然后做NTT即可。当然如果你非得long double大力FFT也没人管你,能AC就好)
考场5分代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cctype>
 6 typedef long long int lli;
 7 using namespace std;
 8 const int maxe=1e3+1e2;
 9 
10 lli fac[maxe],inv[maxe];
11 bool vis[maxe];
12 int mod,p;
13 
14 inline lli lucas(lli n,lli m) {
15     if( n < m ) return 0;
16     if( n < mod && m < mod ) return fac[n] * inv[m] * inv[n-m] % mod;
17     return lucas(n/mod,m/mod) * lucas(n%mod,m%mod) % mod;
18 }
19 inline lli fastpow(lli base,int tim) {
20     lli ret = 1;
21     while(tim) {
22         if( tim & 1 ) ret = ret * base % mod;
23         if( tim >>= 1 ) base = base * base % mod;
24     }
25     return ret;
26 }
27 
28 template<typename T>
29 inline T read() {
30     T ret = 0; char ch;
31     while( !isdigit(ch=getchar()) );
32     do ret = ret * 10 + ch - '0'; while( isdigit(ch=getchar()) );
33     return ret;
34 }
35 
36 int main() {
37     static int T,siz;
38     static lli n,m,t,ans;
39     T = read<int>();
40     while(T--) {
41         n = read<lli>() , m = read<lli>() , t = read<lli>() , mod = read<int>() , memset(vis,0,p=read<int>()) , siz = read<int>() , ans = 0;
42         while( siz-- ) vis[read<int>()] = 1;
43         *fac = 1; for(int i=1;i<mod;i++) fac[i] = fac[i-1] * i % mod;
44         inv[mod-1] = fastpow(fac[mod-1],mod-2); for(int i=mod-1;~i;i--) inv[i-1] = inv[i] * i % mod;
45         for(lli i=0;i<=n;i++) if( vis[i%p] ) ans += lucas(n,i) * lucas(m,t-i) * lucas(t,i) % mod , ans %= mod;
46         printf("%lld\n",ans);
47     }
48     return 0;
49 }
View Code

正解代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cctype>
  6 #define debug cout
  7 typedef long long int lli;
  8 using namespace std;
  9 const int maxn=3e3+1e2;
 10 
 11 namespace NTT {
 12     const int mod=998244353,g=3;
 13     inline int add(const int &x,const int &y) {
 14         const int ret = x + y;
 15         return ret >= mod ? ret - mod : ret;
 16     }
 17     inline int sub(const int &x,const int &y) {
 18         const int ret = x - y;
 19         return ret < 0 ? ret + mod : ret;
 20     }
 21     inline int mul(const int &x,const int &y) {
 22         return (lli) x * y % mod;
 23     }
 24     inline void mule(int &dst,const int &x) {
 25         dst = (lli) dst * x % mod;
 26     }
 27     inline int fastpow(int base,int tim) {
 28         int ret = 1;
 29         while(tim) {
 30             if( tim & 1 ) mule(ret,base);
 31             if( tim >>= 1 ) mule(base,base);
 32         }
 33         return ret;
 34     }
 35     inline void NTT(int* dst,int n,int tpe) {
 36         for(int i=0,j=0;i<n;i++) {
 37             if( i < j ) swap(dst[i],dst[j]);
 38             for(int t=n>>1;(j^=t)<t;t>>=1) ;
 39         }
 40         for(int len=2,h=1;len<=n;len<<=1,h<<=1) {
 41             int per = fastpow(g,mod/len);
 42             if( !~tpe ) per = fastpow(per,mod-2);
 43             for(int st=0;st<n;st+=len) {
 44                 int w = 1;
 45                 for(int pos=0;pos<h;pos++) {
 46                     const int u = dst[st+pos] , v = mul(dst[st+pos+h],w);
 47                     dst[st+pos] = add(u,v) , dst[st+pos+h] = sub(u,v) , mule(w,per);
 48                 }
 49             }
 50         }
 51         if( !~tpe ) {
 52             const int inv = fastpow(n,mod-2);
 53             for(int i=0;i<n;i++) mule(dst[i],inv);
 54         }
 55     }
 56     inline void mul(int* dst,int *sou,int ld,int ls) {
 57         int len; for(len=1;len<=ld+ls;len<<=1) ;
 58         for(int i=ld;i<len;i++) sou[i] = 0;
 59         for(int i=ls;i<len;i++) dst[i] = 0;
 60         NTT(dst,len,1) , NTT(sou,len,1);
 61         for(int i=0;i<len;i++) mule(dst[i],sou[i]);
 62         NTT(dst,len,-1);
 63     }
 64 }
 65 
 66 bool vis[maxn];
 67 int fac[maxn],inv[maxn],f[2][maxn];
 68 lli n,m,t;
 69 int mod,p; // mod is mod of lucas and mod of answer .
 70 
 71 inline int c(int n,int m) {
 72     if( n < m ) return 0;
 73     return fac[n] * inv[m] * inv[n-m] % mod;
 74 }
 75 inline void trans(int* dst,int* sou) {
 76     static int tp[maxn]; memset(tp,0,sizeof(tp));
 77     for(int i=0;i<p;i++) tp[i*mod%p] += sou[i];
 78     for(int i=0;i<p;i++) tp[i] %= mod;
 79     NTT::mul(dst,tp,p,p);
 80     for(int i=p;i<p<<1;i++) dst[i%p] += dst[i];
 81     for(int i=0;i<p;i++) dst[i] %= mod;
 82 }
 83 inline void initseq(int* dst,int bitn,int bitm,int bitt) {
 84     for(int i=0;i<p;i++) dst[i] = 0;
 85     for(int i=0;i<=bitn&&i<=bitt;i++) {
 86         dst[i%p] += c(bitn,i) * c(bitm,bitt-i) *  c(bitt,i) % mod;
 87     }
 88     for(int i=0;i<p;i++) dst[i] %= mod;
 89 }
 90 
 91 inline int fastpow(int base,int tim) {
 92     int ret = 1;
 93     while(tim) {
 94         if( tim & 1 ) ret = ret * base % mod;
 95         if( tim >>= 1 ) base = base * base % mod;
 96     }
 97     return ret;
 98 }
 99 inline void init() {
100     memset(f,0,sizeof(f));
101     *fac = 1; for(int i=1;i<mod;i++) fac[i] = fac[i-1] * i % mod;
102     inv[mod-1] = fastpow(fac[mod-1],mod-2); for(int i=mod-1;i;i--) inv[i-1] = inv[i] * i % mod;
103 }
104 inline void getbit(int* dst,int &len,lli x) {
105     memset(dst,0,280) , len = 0;
106     while(x) dst[++len] = x % mod , x /= mod;
107 }
108 
109 template<typename T>
110 inline T read() {
111     T  ret = 0; char ch;
112     while( !isdigit(ch=getchar()) ) ;
113     do ret = ret * 10 + ch - '0'; while( isdigit(ch=getchar()) );
114     return ret;
115 }
116 
117 int bitn[70],bitm[70],bitt[70],tn,tm,tt;
118 
119 int main() {
120     static int T,siz,cur,ans;
121     T = read<int>();
122     while(T--) {
123         n = read<lli>() , m = read<lli>() , t = read<lli>() , mod = read<int>() , memset(vis,0,p=read<int>()) , siz = read<int>();
124         while(siz--) vis[read<int>()] = 1;
125         init() , ans = 0 , getbit(bitn,tn,n) , getbit(bitm,tm,m) , getbit(bitt,tt,t);
126         initseq(f[cur=0],bitn[tt],bitm[tt],bitt[tt]);
127         for(int i=tt-1;i;i--) cur ^= 1 , initseq(f[cur],bitn[i],bitm[i],bitt[i]) , trans(f[cur],f[cur^1]);
128         for(int i=0;i<p;i++) if( vis[i] ) ans += f[cur][i];
129         printf("%d\n",ans%mod);
130     }
131     return 0;
132 }
View Code

 


T3:


考虑点分治,那么每个点最优解的路径只有两种:过当前分治重心的和不过分治重心的。
对于不过分治重心的,我们递归处理,考虑过分治重心的,显然只有每个点的最优路径才会更新答案。
好,我们到trie树中查出最大xor和取得最大xor时这个点对应的点,然后到原树上给这条链打上max标记即可。
注意这个标记可以用树链剖分+线段树实现,然而会多一个log。考虑我们只用查询一次,用ST表打标记就好啦。
另外,每个点的最优决策可能在这个点子树的前面也可能在后面,而这个点取最优解的时候对应的不一定是另一个点的最优解。
所以,需要在点分治的时候正反做两遍。否则大概会WA。
代码:

  1 #pragma GCC optimize("Ofast","no-stack-protector")
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<utility>
  6 #include<cctype>
  7 #include<vector>
  8 #define debug cout
  9 using namespace std;
 10 const int maxn=1e5+1e2,maxe=5e6+1e2,maxl=20;
 11 const int inf=0x3f3f3f3f;
 12 
 13 int ans[maxn],n;
 14 namespace Tree {
 15     int s[maxn],t[maxn<<1],nxt[maxn<<1];
 16     int dep[maxn],lazy[maxn][maxl],anc[maxn][maxl];
 17     inline void coredge(int from,int to) {
 18         static int cnt;
 19         t[++cnt] = to , nxt[cnt] = s[from] , s[from] = cnt;
 20     }
 21     inline void addedge(int a,int b) {
 22         coredge(a,b) , coredge(b,a);
 23     }
 24     inline void pre(int pos) {
 25         for(int at=s[pos];at;at=nxt[at]) if( t[at] != *anc[pos] ) dep[t[at]] = dep[*anc[t[at]]=pos] + 1 , pre(t[at]);
 26     }
 27     inline void init() {
 28         for(int j=1;j<maxl;j++) for(int i=1;i<=n;i++) anc[i][j] = anc[anc[i][j-1]][j-1];
 29     }
 30     inline int lca(int x,int y) {
 31         if( dep[x] < dep[y] ) swap(x,y);
 32         for(int i=maxl-1;~i;i--) if( dep[x] - ( 1 << i ) >= dep[y] ) x = anc[x][i];
 33         if( x == y ) return x;
 34         for(int i=maxl-1;~i;i--) if( anc[x][i] != anc[y][i] ) x = anc[x][i] , y = anc[y][i];
 35         return *anc[x];
 36     }
 37     inline int getlen(int s,int f) {
 38         return dep[s] - dep[f] + 1;
 39     }
 40     inline void markchain(int x,int dep,int v) { // mark dep points .
 41         for(int i=maxl-1;~i;i--) if( dep - ( 1 << i ) >= 0 ) {
 42             lazy[x][i] = max( lazy[x][i] , v ) , dep -= 1 << i , x = anc[x][i];
 43         }
 44     }
 45     inline void pushall() {
 46         for(int j=maxl-1;j;j--) for(int i=1;i<=n;i++) {
 47             lazy[i][j-1] = max( lazy[i][j-1] , lazy[i][j] ) ,
 48             lazy[anc[i][j-1]][j-1] = max( lazy[anc[i][j-1]][j-1] , lazy[i][j] );
 49         }
 50         for(int i=1;i<=n;i++) ans[i] = *lazy[i];
 51     }
 52 }
 53 
 54 typedef pair<int,int> pii;
 55 inline pii mp(const int &x,const int &y) { return (pii){x,y}; }
 56 
 57 int root;
 58 struct Trie { // dep from 30 downto -1 becaus 2^30 > 1e9 so it can't have bit 2^31 .
 59     int ch[maxe][2],id[maxe],cnt; // identity of leaf node .
 60     inline void insert(int &pos,int dep,const int &val,const int &iid) {
 61         if( !pos ) pos = ++cnt;
 62         if( !~dep ) return void(id[pos] = iid);
 63         int bit = ( val >> dep ) & 1; insert(ch[pos][bit],dep-1,val,iid);
 64     }
 65     inline pii query(int pos,int dep,const int &val) {
 66         if( !~dep ) return mp(0,id[pos]);
 67         int bit = ( ( val >> dep ) & 1 ) ^ 1;
 68         if( ch[pos][bit] ) {
 69             pii qs = query(ch[pos][bit],dep-1,val);
 70             return mp(qs.first|(1<<dep),qs.second);
 71         } else return query(ch[pos][bit^1],dep-1,val); // pos must have at least one son .
 72     }
 73     inline void reset() {
 74         ++cnt , memset(ch,0,sizeof(ch[0])*cnt) , memset(id,0,sizeof(id[0])*cnt) , cnt = 0 , root = 0;
 75     }
 76 }trie;
 77 
 78 namespace TDAC {
 79     int s[maxn],t[maxn<<1],nxt[maxn<<1],l[maxn<<1];
 80     int siz[maxn],mxs[maxn],ban[maxn],vs[maxn],is[maxn],cnt;
 81     inline void coredge(int from,int to,int len) {
 82         static int cnt;
 83         t[++cnt] = to , l[cnt] = len , nxt[cnt] = s[from] , s[from] = cnt;
 84     }
 85     inline void addedge(int a,int b,int l) {
 86         coredge(a,b,l) , coredge(b,a,l);
 87     }
 88     inline void getroot(int pos,int fa,const int &fs,int &rt) {
 89         siz[pos] = 1 , mxs[pos] = 0;
 90         for(int at=s[pos];at;at=nxt[at]) if( t[at] != fa && !ban[t[at]] ) getroot(t[at],pos,fs,rt) , siz[pos] += siz[t[at]] , mxs[pos] = max( mxs[pos] , siz[t[at]] );
 91         if( ( mxs[pos] = max( mxs[pos] , fs - siz[pos]) ) <= mxs[rt] ) rt = pos; // *mxs == inf .
 92     }
 93     inline void dfs(int pos,int fa,int su) {
 94         vs[++cnt] = su , is[cnt] = pos;
 95         for(int at=s[pos];at;at=nxt[at]) if( t[at] != fa && !ban[t[at]] ) dfs(t[at],pos,su^l[at]);
 96     }
 97     inline void solve(int pos,int fs) {
 98         if( fs == 1 ) return;
 99         int rt = 0; *mxs = inf , getroot(pos,-1,fs,rt) , ban[rt] = 1;
100 
101         static vector<int> sons,lens; sons.clear() , lens.clear();
102         for(int at=s[rt];at;at=nxt[at]) if( !ban[t[at]] ) sons.push_back(t[at]) , lens.push_back(l[at]);
103 
104         trie.reset() , trie.insert(root,30,0,rt);
105         for(unsigned i=0;i<sons.size();i++) {
106             cnt = 0 , dfs(sons[i],rt,lens[i]);
107             for(int i=1;i<=cnt;i++) {
108                 pii qry = trie.query(root,30,vs[i]); int lca = Tree::lca(is[i],qry.second);
109                 Tree::markchain(is[i],Tree::getlen(is[i],lca),qry.first) , Tree::markchain(qry.second,Tree::getlen(qry.second,lca),qry.first);
110             }
111             for(int i=1;i<=cnt;i++) trie.insert(root,30,vs[i],is[i]);
112         }
113 
114         reverse(sons.begin(),sons.end()) , reverse(lens.begin(),lens.end());
115         
116         trie.reset() , trie.insert(root,30,0,rt);
117         for(unsigned i=0;i<sons.size();i++) {
118             cnt = 0 , dfs(sons[i],rt,lens[i]);
119             for(int i=1;i<=cnt;i++) {
120                 pii qry = trie.query(root,30,vs[i]); int lca = Tree::lca(is[i],qry.second);
121                 Tree::markchain(is[i],Tree::getlen(is[i],lca),qry.first) , Tree::markchain(qry.second,Tree::getlen(qry.second,lca),qry.first);
122             }
123             for(int i=1;i<=cnt;i++) trie.insert(root,30,vs[i],is[i]);
124         }
125 
126         for(int at=s[rt];at;at=nxt[at]) if( !ban[t[at]] ) solve(t[at],siz[t[at]]<siz[rt]?siz[t[at]]:fs-siz[rt]);
127     }
128 }
129 
130 namespace IO {
131     inline char nextchar() {
132         static const int BS = 1 << 21;
133         static char buf[BS],*st,*ed;
134         if( st == ed ) ed = buf + fread(st=buf,1,BS,stdin);
135         return st == ed ? -1 : *st++;
136     }
137     inline int getint() {
138         int ret = 0; char ch;
139         while( !isdigit(ch=nextchar()) ) ;
140         do ret = ret * 10 + ch - '0'; while( isdigit(ch=nextchar()) );
141         return ret;
142     }
143 }
144 using IO::getint;
145 
146 int main() {
147     n = getint();
148     for(int i=1,a,b,l;i<n;i++) a = getint() , b = getint() , l = getint() , Tree::addedge(a,b) , TDAC::addedge(a,b,l);
149     Tree::pre(1) , Tree::init() , TDAC::solve(1,n) , Tree::pushall();
150     for(int i=1;i<=n;i++) printf("%d\n",ans[i]);
151     return 0;
152 }
View Code

 


这次虽然又是rank1了,不过和第二只差5分......
被NOIP题卡了,不开心。

posted @ 2018-06-29 17:08  Cmd2001  阅读(292)  评论(0编辑  收藏  举报