• 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]?' ':'
    ');
    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
    ",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
    ",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
    ",ans[i]);
    151     return 0;
    152 }
    View Code


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

  • 相关阅读:
    Java 1 (JVM、JRE、JDK之间的关系)
    Java 0 (jdk下载安装及环境配置)
    推荐之链接
    idea 2019激活码
    Mock数据使用的Util
    mybatis慢查询配置
    logback参考配置
    Linux网络实时监控配置
    jmeter插件JMeterPlugins-Standard 压力测试
    ZoneDateTime 转换Date
  • 原文地址:https://www.cnblogs.com/Cmd2001/p/9244396.html
Copyright © 2020-2023  润新知