北京集训:20180316

吃了某种抑制神经的药的蒟蒻真是药丸......
别问我为什么推到今天才补,才不告诉你我拖延症犯了......

T1:


一看就是不可做的构造题......
前20分爆搜,后20分估计是什么状压,然而并不会写......
考虑f[i][j][k][l]表示礼物i在j,k在l是否可行,
我们可以通过一个类似于点分治的dfs预处理出这些信息。
如果我们把每个礼物在某个节点看做新图上一个点的话,我们就要在新图上找一个大小为n的团......
最大团什么的,不是NP问题吗?这玩意人干事?
算了,写个爆搜搞搞就好......
成绩出来发现跑过了4个点,第一个点WA了woc......
正解是2-sat。
考虑f[i][j][0/1]表示礼物i是否在点j的的子树中。
那么对于礼物x,y经过点pos,我们需要:
f[son][x]&f[son][y] = 0
f[pos][x]|f[pos][y] = 1
f[son][x]&f[son2][x] = 0
f[pos][x] -> f[fa][x]。
然后2-sat建图按照tarjan求出强连通的顺序输出方案即可。
然而写挂了还是30分......
考场30分暴力:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<bitset>
 7 using namespace std;
 8 const int maxn=252;
 9 
10 int s[maxn],t[maxn<<1],nxt[maxn<<1];
11 bitset<maxn> can[maxn][maxn][maxn],now[maxn][maxn];
12 bitset<maxn> sons[maxn],full;
13 vector<pair<int,int> > vs[maxn];
14 bool bad[maxn][maxn];
15 int fm[maxn],ans[maxn];
16 int n,m,q;
17 
18 inline void addedge(int from,int to) {
19     static int cnt = 0;
20     t[++cnt] = to , nxt[cnt] = s[from] , s[from] = cnt;
21 }
22 inline void dfs(int pos,int fa,int bel) {
23     sons[bel][pos] = 1 , fm[pos] = bel;
24     for(int at=s[pos];at;at=nxt[at]) if( t[at] != fa ) dfs(t[at],pos,bel);
25 }
26 inline void solvepos(int pos) {
27     if( !vs[pos].size() ) return;
28     for(int at=s[pos];at;at=nxt[at]) {
29         sons[t[at]] &= 0;
30         dfs(t[at],pos,t[at]);
31     }
32     for(unsigned j=0;j<vs[pos].size();j++) {
33         const int x = vs[pos][j].first , y = vs[pos][j].second;
34         for(int i=1;i<=n;i++) if( i != pos ) {
35             can[x][i][y] &= ( full ^ sons[fm[i]] );
36             can[y][i][x] &= ( full ^ sons[fm[i]] );
37         }
38     }
39 }
40 inline void cpy(int dst,int sou) {
41     for(int i=1;i<=m;i++) now[dst][i] = now[sou][i];
42 }
43 inline void afs(int pos) {
44     if( pos == 1 ) {
45         for(int i=1;i<=m;i++)
46             for(int j=1;j<=m;j++)
47                 now[i][j] = full;
48     }
49     if( pos > m ) {
50         for(int i=1;i<=m;i++) printf("%d%c",ans[i],i!=m?' ':'\n');
51         exit(0);
52     }
53     for(int i=1,fail;i<=n;i++) if( now[pos][pos][i] && !bad[pos][i] ) {
54         ans[pos] = i , fail = 0;
55         cpy(pos+1,pos);
56         for(int j=1;j<=m;j++) {
57             now[pos+1][j] &= can[pos][i][j];
58             if( !now[pos+1][j].count() ) {
59                 fail = 1;
60                 break;
61             }
62         }
63         if( !fail ) afs(pos+1);
64     }
65 }
66 inline void getbad() {
67     for(int i=1;i<=m;i++)
68         for(int j=1;j<=n;j++)
69             for(int k=1;k<=m;k++)
70                 if( !can[i][j][k].count() ) {
71                     bad[i][j] = 1;
72                     break;
73                 }
74 }
75 int main() {
76     scanf("%d%d%d",&n,&m,&q);
77     for(int i=1,a,b;i<n;i++) {
78         scanf("%d%d",&a,&b);
79         addedge(a,b) , addedge(b,a);
80     }
81     for(int i=1,a,b,t;i<=q;i++) {
82         scanf("%d%d%d",&a,&b,&t);
83         vs[t].push_back(make_pair(a,b));
84     }
85     for(int i=1;i<=n;i++) full[i] = i;
86     for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) for(int k=1;k<=m;k++) can[i][j][k] = full;
87     for(int i=1;i<=n;i++) solvepos(i);
88     getbad();
89     afs(1);
90     return 0;
91 }
View Code

写挂的30分正解:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 #define debug cout
  7 using namespace std;
  8 const int maxn=13000,maxe=6300000,maxl=300;
  9 
 10 int n,m;
 11 int ans[maxl],dep[maxl];
 12 
 13 namespace Tsat {
 14     int s[maxn],t[maxe],nxt[maxe];
 15     int vis[maxn],dfn[maxn],low[maxn],bel[maxn],dd,iid;
 16     int ins[maxn],stk[maxn],top;
 17     inline void addedge(int from,int to) {
 18         static int cnt = 0;
 19         t[++cnt] = to , nxt[cnt] = s[from] , s[from] = cnt;
 20     }
 21     inline int cov(int pri,int pos,int sta) { // sta == 0 means not , sta == 1 means yes .
 22         return m * 2 * ( pri - 1 ) + ( pos - 1 ) * 2 + 1 + sta;
 23     }
 24     inline void dfs(int pos) {
 25         vis[pos] = 1;
 26         stk[++top] = pos , ins[pos] = 1;
 27         low[pos] = dfn[pos] = ++dd;
 28         for(int at=s[pos];at;at=nxt[at])
 29             if( !vis[t[at]] ) {
 30                 dfs(t[at]);
 31                 low[pos] = min( low[pos] , low[t[at]] );
 32             } else if( ins[t[at]] ) low[pos] = min( low[pos] , dfn[t[at]] );
 33         if( low[pos] == dfn[pos] ) {
 34             ++iid;
 35             do {
 36                 const int x = stk[top--];
 37                 bel[x] = iid , ins[x] = 0;
 38             } while( ins[pos] );
 39         }
 40     }
 41     inline void findway() {
 42         for(int i=1;i<=m;i++) ans[i] = 1;
 43         for(int i=1;i<=m;i++)
 44             for(int j=1;j<=n;j++) {
 45                 const int c0 = cov(i,j,0) , c1 = cov(i,j,1);
 46                 if( bel[c1] < bel[c0] && dep[ans[i]] < dep[j] ) ans[i] = j;
 47             }
 48     }
 49     inline void work() {
 50         for(int i=1;i<=n*m*2;i++) if( !vis[i] ) dfs(i);
 51         findway();
 52     }
 53 }
 54 
 55 namespace Tree {
 56     int s[maxl],t[maxl<<1],nxt[maxl<<1];
 57     vector<pair<int,int> > vec[maxl];
 58     inline void addedge(int from,int to) {
 59         static int cnt = 0;
 60         t[++cnt] = to , nxt[cnt] = s[from] , s[from] = cnt;
 61     }
 62     inline void dfs(int pos,int fa) {
 63         vector<int> sons;
 64         for(int at=s[pos];at;at=nxt[at]) if( t[at] != fa ) {
 65             sons.push_back(t[at]);
 66             dep[t[at]] = dep[pos] + 1 , dfs(t[at],pos);
 67         }
 68         #define cov(x,y,z) Tsat::cov(x,y,z)
 69         #define _addedge(a,b) Tsat::addedge(a,b)
 70         for(unsigned i=0;i<vec[pos].size();i++) {
 71             const int x = vec[pos][i].first , y = vec[pos][i].second;
 72             for(unsigned j=0;j<sons.size();j++) {
 73                 const int c = sons[j];
 74                 _addedge(cov(x,c,1),cov(y,c,0)) ,
 75                 _addedge(cov(y,c,1),cov(x,c,0)) ;
 76             }
 77             _addedge(cov(x,pos,0),cov(y,pos,1)) ,
 78             _addedge(cov(y,pos,0),cov(x,pos,1)) ;
 79         }
 80         if( ~fa ) for(int k=1;k<=m;k++) _addedge(cov(k,pos,1),cov(k,fa,1));
 81         for(unsigned i=0;i<sons.size();i++)
 82             for(unsigned j=i+1;j<sons.size();j++)
 83                 for(int k=1;k<=m;k++) {
 84                     const int x = sons[i] , y = sons[j];
 85                     _addedge(cov(k,x,1),cov(k,y,0)) ,
 86                     _addedge(cov(k,y,1),cov(k,x,0)) ;
 87                 }
 88     }
 89 }
 90 
 91 int main() {
 92     static int q;
 93     scanf("%d%d%d",&n,&m,&q);
 94     for(int i=1,a,b;i<n;i++) {
 95         using Tree::addedge;
 96         scanf("%d%d",&a,&b) , addedge(a,b) , addedge(b,a);
 97     }
 98     for(int i=1,a,b,c;i<=q;i++) {
 99         using Tree::vec;
100         scanf("%d%d%d",&a,&b,&c) , vec[c].push_back(make_pair(a,b));
101     }
102     dep[1] = 1;
103     Tree::dfs(1,-1);
104     Tsat::work();
105     for(int i=1;i<=m;i++) printf("%d%c",ans[i],i!=m?' ':'\n');
106     return 0;
107 }
108 
109 /*
110 5 5 5
111 1 2
112 1 3
113 3 4
114 2 5
115 1 1 2
116 2 4 2
117 5 4 2
118 2 4 5
119 1 4 1
120 
121 2 5 1 1 2
122 */
View Code

Commit @ 2018.03.19
这个2sat终于调对了......
其实我们还需要加一条边:!f[fa][x] -> !f[pos][x]。
然后就是数组又开小了,250*250是1.3e5级别的,我开了1.3e4......
真·蒟蒻不识数
代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 #define debug cout
  7 using namespace std;
  8 const int maxn=130000,maxe=6300000,maxl=300;
  9 
 10 int n,m;
 11 int ans[maxl],dep[maxl];
 12 
 13 vector<pair<int,int> > es;
 14 namespace Tsat {
 15     int s[maxn],t[maxe],nxt[maxe];
 16     int vis[maxn],dfn[maxn],low[maxn],bel[maxn],dd,iid;
 17     int ins[maxn],stk[maxn],top;
 18     inline void addedge(int from,int to) {
 19         static int cnt = 0;
 20         t[++cnt] = to , nxt[cnt] = s[from] , s[from] = cnt;
 21         es.push_back(make_pair(from,to));
 22     }
 23     inline int cov(int pri,int pos,int sta) { // sta == 0 means not , sta == 1 means yes .
 24         return m * 2 * ( pri - 1 ) + ( pos - 1 ) * 2 + 1 + sta;
 25     }
 26     inline void dfs(int pos) {
 27         vis[pos] = 1;
 28         stk[++top] = pos , ins[pos] = 1;
 29         low[pos] = dfn[pos] = ++dd;
 30         for(int at=s[pos];at;at=nxt[at])
 31             if( !vis[t[at]] ) {
 32                 dfs(t[at]);
 33                 low[pos] = min( low[pos] , low[t[at]] );
 34             } else if( ins[t[at]] ) low[pos] = min( low[pos] , dfn[t[at]] );
 35         if( low[pos] == dfn[pos] ) {
 36             ++iid;
 37             do {
 38                 const int x = stk[top--];
 39                 bel[x] = iid , ins[x] = 0;
 40             } while( ins[pos] );
 41         }
 42     }
 43     inline void findway() {
 44         for(int i=1;i<=m;i++) ans[i] = 1;
 45         for(int i=1;i<=m;i++)
 46             for(int j=1;j<=n;j++) {
 47                 const int c0 = cov(i,j,0) , c1 = cov(i,j,1);
 48                 if( bel[c1] < bel[c0] && dep[ans[i]] < dep[j] ) ans[i] = j;
 49             }
 50     }
 51     inline void work() {
 52         for(int i=1;i<=n*m*2;i++) if( !vis[i] ) dfs(i);
 53         findway();
 54     }
 55 }
 56 
 57 namespace Tree {
 58     int s[maxl],t[maxl<<1],nxt[maxl<<1];
 59     vector<pair<int,int> > vec[maxl];
 60     vector<int> sons[maxl];
 61     inline void addedge(int from,int to) {
 62         static int cnt = 0;
 63         t[++cnt] = to , nxt[cnt] = s[from] , s[from] = cnt;
 64     }
 65     inline void dfs(int pos,int fa) {
 66         for(int at=s[pos];at;at=nxt[at]) if( t[at] != fa ) {
 67             sons[pos].push_back(t[at]);
 68             dep[t[at]] = dep[pos] + 1 , dfs(t[at],pos);
 69         }
 70         #define cov(x,y,z) Tsat::cov(x,y,z)
 71         #define _addedge(a,b) Tsat::addedge(a,b)
 72         for(unsigned i=0;i<vec[pos].size();i++) {
 73             const int x = vec[pos][i].first , y = vec[pos][i].second;
 74             for(unsigned j=0;j<sons[pos].size();j++) {
 75                 const int c = sons[pos][j];
 76                 _addedge(cov(x,c,1),cov(y,c,0)) ,
 77                 _addedge(cov(y,c,1),cov(x,c,0)) ;
 78             }
 79             _addedge(cov(x,pos,0),cov(y,pos,1)) , 
 80             _addedge(cov(y,pos,0),cov(x,pos,1)) ;
 81         }
 82         if( ~fa ) for(int k=1;k<=m;k++) {
 83             _addedge(cov(k,pos,1),cov(k,fa,1));
 84             _addedge(cov(k,fa,0),cov(k,pos,0)); // !
 85         }
 86         for(unsigned i=0;i<sons[pos].size();i++)
 87             for(unsigned j=i+1;j<sons[pos].size();j++)
 88                 for(int k=1;k<=m;k++) {
 89                     const int x = sons[pos][i] , y = sons[pos][j];
 90                     _addedge(cov(k,x,1),cov(k,y,0)) ,
 91                     _addedge(cov(k,y,1),cov(k,x,0)) ;
 92                 }
 93     }
 94 }
 95 
 96 int main() {
 97     static int q;
 98     scanf("%d%d%d",&n,&m,&q);
 99     for(int i=1,a,b;i<n;i++) {
100         using Tree::addedge;
101         scanf("%d%d",&a,&b) , addedge(a,b) , addedge(b,a);
102     }
103     for(int i=1,a,b,c;i<=q;i++) {
104         using Tree::vec;
105         scanf("%d%d%d",&a,&b,&c) , vec[c].push_back(make_pair(a,b));
106     }
107     dep[1] = 1;
108     Tree::dfs(1,-1);
109     Tsat::work();
110     sort(es.begin(),es.end());
111     for(int i=1;i<=m;i++) printf("%d%c",ans[i],i!=m?' ':'\n');
112     return 0;
113 }
View Code


T2:


显然有一个非常好写的k^2插值。
然而我连拉格朗日插值都不会......
写了个多项式取模乱搞,卡成O(k^3)一分没有......
只有第一个点的10分。
其实拉格朗日插值不用求出多项式的,只要把你需要求值的x带进去即可。
正解为下面的一堆......


求出g然后用g插n即可。
拉格朗日插值的作用大概就是是用小范围的信息计算大范围的信息。
考场10分代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cstdlib>
  6 #define debug cout
  7 typedef long long int lli;
  8 using namespace std;
  9 const int maxn=4e3+1e2;
 10 const int mod=1e9+7;
 11 
 12 lli inv[maxn];
 13 int in[maxn];
 14 int k;
 15 
 16 inline lli fastpow(lli base,int tim) {
 17     lli ret = 1;
 18     while( tim ) {
 19         if( tim & 1 ) ret = ret * base % mod;
 20         if( tim >>= 1 ) base = base * base % mod;
 21     }
 22     return ret;
 23 }
 24 
 25 struct Poly {
 26     lli dat[maxn];
 27     Poly(int aa=0,int bb=0) {
 28         memset(dat,0,sizeof(dat));
 29         dat[1] = ( aa % mod + mod ) % mod , dat[0] = ( bb % mod + mod ) % mod;
 30     }
 31     lli& operator [] (const int &x) {
 32         return dat[x];
 33     }
 34     const lli& operator [] (const int &x) const {
 35         return dat[x];
 36     }
 37     friend Poly operator * (const Poly &a,const Poly &b) {
 38         Poly ret;
 39         for(int i=0;i<k+2;i++) for(int j=0;j<k+2;j++) ( ret[i+j] += a[i] * b[j] % mod ) %= mod;
 40         return ret;
 41     }
 42     friend Poly operator / (const Poly &a,const Poly &b) {
 43         Poly ret,tp=a;
 44         int hgh = k+2;
 45         while( !b[hgh] ) --hgh;
 46         for(int i=(k+2)<<1;i>=hgh;i--) if( tp[i] ) {
 47             const lli mul = tp[i] * fastpow(b[hgh],mod-2);
 48             ret[i-hgh] = mul;
 49             for(int t=0;t<=hgh;t++) ( ( tp[i-t] -= b[hgh-t] * mul % mod ) += mod ) %= mod;
 50         }
 51         return ret;
 52     }
 53     friend Poly operator + (const Poly &a,const Poly &b) {
 54         Poly ret;
 55         for(int i=0;i<k+2;i++)
 56             ret[i] = ( a[i] + b[i] ) % mod;
 57         return ret;
 58     }
 59     friend Poly operator * (const Poly &a,const lli &t) {
 60         Poly ret;
 61         for(int i=0;i<k+2;i++) ret[i] = a[i] * t % mod;
 62         return ret;
 63     }
 64     inline lli calc(lli base) {
 65         lli ret = 0 , now = 1;
 66         for(int i=0;i<k;i++) {
 67             ( ret += now * dat[i] % mod ) %= mod ,
 68             now = now * base % mod;
 69         }
 70         return ret;
 71     }
 72 }pol;
 73 
 74 inline Poly getval() {
 75     Poly ret,pi(0,1),now;
 76     for(int i=0;i<k;i++) pi = pi * Poly(1,-i);
 77     for(int i=0;i<k;i++) {
 78         lli mul = in[i];
 79         for(int j=0;j<k;j++) if( i != j ) {
 80             mul = mul * inv[abs(i-j)] % mod;
 81             if( i - j < 0 ) mul = mod - mul;
 82         }
 83         now = pi / Poly(1,-i);
 84         ret = ret + now * mul;
 85     }
 86     return ret;
 87 }
 88 
 89 inline void getinv() {
 90     static lli fac[maxn];
 91     *fac = 1;
 92     for(int i=1;i<=k;i++) fac[i] = fac[i-1] * i % mod;
 93     inv[k] = fastpow(fac[k],mod-2);
 94     for(int i=k;i;i--) inv[i-1] = inv[i] * i % mod;
 95     for(int i=1;i<=k;i++) inv[i] = inv[i] * fac[i-1] % mod;
 96 }
 97 
 98 int main() {
 99     static int n,q;
100     static lli ans;
101     scanf("%d%d%d",&n,&k,&q) , ++k;
102     for(int i=0;i<k;i++) scanf("%d",in+i);
103     if( n < k ) {
104         for(int i=0;i<=n;i++) ans = ( ans + in[i] * fastpow(q,i) % mod ) % mod;
105         return printf("%lld\n",ans),0;
106     }
107     getinv();
108     pol = getval();
109     for(int i=0;i<=n;i++) ans = ( ans + pol.calc(i) * fastpow(q,i) % mod ) % mod;
110     printf("%lld\n",ans);
111     return 0;
112 }
View Code

修正40分暴力:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cstdlib>
  6 #define debug cout
  7 typedef long long int lli;
  8 using namespace std;
  9 const int maxn=5e5+1e2;
 10 const int mod=1e9+7;
 11 
 12 struct Node {
 13     lli a,b;
 14     friend Node operator + (const Node &a,const Node &b) {
 15         return (Node){(a.a+b.a)%mod,(a.b+b.b)%mod};
 16     }
 17     friend Node operator * (const Node &a,const lli &x) {
 18         return (Node){a.a*x%mod,a.b*x%mod};
 19     }
 20     friend Node operator + (const Node &a,const lli &x) {
 21         return (Node){a.a,(a.b+x)%mod};
 22     }
 23 }ns[maxn];
 24 
 25 lli in[maxn],g[maxn],fac[maxn],inv[maxn];
 26 int k,p;
 27 
 28 inline lli fastpow(lli base,int tim) {
 29     lli ret = 1;
 30     while(tim) {
 31         if( tim & 1 ) ret = ret * base % mod;
 32         if( tim >>= 1 ) base = base * base % mod;
 33     }
 34     return ret;
 35 }
 36 
 37 inline void pre() {
 38     *fac = 1;
 39     for(int i=1;i<=k;i++) fac[i] = fac[i-1] * i % mod;
 40     inv[k] = fastpow(fac[k],mod-2);
 41     for(int i=k;i;i--) inv[i-1] = inv[i] * i % mod;
 42 }
 43 inline lli c(int n,int m) {
 44     return fac[n] * inv[m] % mod * inv[n-m] % mod;
 45 }
 46 
 47 namespace Inter {
 48     lli fac[maxn],facrev[maxn],pprv[maxn],ssuf[maxn],*prv=pprv+1,*suf=ssuf+1;
 49     inline lli getmul(int p) {
 50         return p ? fac[p] * facrev[k-p-1] % mod : facrev[k-1];
 51     }
 52     inline lli getval(lli* in,lli x) {
 53         lli ret = 0;
 54         prv[-1] = 1;
 55         for(int i=0;i<k;i++) prv[i] = prv[i-1] * (x-i+mod) % mod;
 56         suf[k] = 1;
 57         for(int i=k-1;~i;i--) suf[i] = suf[i+1] * (x-i+mod) % mod;
 58         for(int i=0;i<k;i++) {
 59             lli now = prv[i-1] * suf[i+1] % mod;
 60             ret = ret + now * in[i] % mod * getmul(i) % mod , ret %= mod;
 61         }
 62         return ret;
 63     }
 64     inline void getinv() {
 65         static lli inv[maxn];
 66         *fac = 1;
 67         for(int i=1;i<=k;i++) fac[i] = fac[i-1] * i % mod;
 68         inv[k] = fastpow(fac[k],mod-2);
 69         for(int i=k;i;i--)inv[i-1] = inv[i] * i % mod;
 70         for(int i=1;i<=k;i++) inv[i] = inv[i] * fac[i-1] % mod;
 71         for(int i=1;i<=k;i++) fac[i] = fac[i-1] * inv[i] % mod;
 72         facrev[0] = 1;
 73         for(int i=1;i<=k;i++) facrev[i] = facrev[i-1] * ( mod - inv[i] ) % mod;
 74     }
 75 }
 76 
 77 inline void getg0() {
 78     static Node now;
 79     int mul = 1;
 80     for(int i=0;i<=k;i++) {
 81         now = now + ns[k-i] * ( mul == 1 ? c(k,i) : mod - c(k,i) );
 82         mul *= -1;
 83     }
 84     g[0] = ( mod - now.b ) % mod * fastpow(now.a,mod-2) % mod;
 85 }
 86 inline void calc() {
 87     const lli inv = fastpow(p,mod-2);
 88     ns[0] = (Node){1,0};
 89     for(int i=1;i<=k;i++) ns[i] = ( ns[i-1] + in[i-1] ) * inv;
 90     getg0();
 91     for(int i=1;i<=k;i++) g[i] = ( g[i-1] + in[i-1] ) % mod * inv % mod;
 92 }
 93 
 94 int main() {
 95     static lli ans,n;
 96     scanf("%lld%d%d",&n,&k,&p) , ++k;
 97     for(int i=0;i<k;i++) scanf("%lld",in+i);
 98     pre() , calc();
 99     Inter::getinv();
100     ans = ( Inter::getval(g,n+1) * fastpow(p,(n+1)%(mod-1)) % mod - g[0] + mod ) % mod;
101     printf("%lld\n",ans);
102     return 0;
103 }
View Code

正解代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cstdlib>
  6 #define debug cout
  7 typedef long long int lli;
  8 using namespace std;
  9 const int maxn=5e5+1e2;
 10 const int mod=1e9+7;
 11 
 12 struct Node {
 13     lli a,b;
 14     friend Node operator + (const Node &a,const Node &b) {
 15         return (Node){(a.a+b.a)%mod,(a.b+b.b)%mod};
 16     }
 17     friend Node operator * (const Node &a,const lli &x) {
 18         return (Node){a.a*x%mod,a.b*x%mod};
 19     }
 20     friend Node operator + (const Node &a,const lli &x) {
 21         return (Node){a.a,(a.b+x)%mod};
 22     }
 23 }ns[maxn];
 24 
 25 lli in[maxn],g[maxn],fac[maxn],inv[maxn];
 26 int k,p;
 27 
 28 inline lli fastpow(lli base,int tim) {
 29     lli ret = 1;
 30     while(tim) {
 31         if( tim & 1 ) ret = ret * base % mod;
 32         if( tim >>= 1 ) base = base * base % mod;
 33     }
 34     return ret;
 35 }
 36 inline lli fastpow_lli(lli base,lli tim) {
 37     lli ret = 1;
 38     while(tim) {
 39         if( tim & 1 ) ret = ret * base % mod;
 40         if( tim >>= 1 ) base = base * base % mod;
 41     }
 42     return ret;
 43 }
 44 
 45 inline void pre() {
 46     *fac = 1;
 47     for(int i=1;i<=k;i++) fac[i] = fac[i-1] * i % mod;
 48     inv[k] = fastpow(fac[k],mod-2);
 49     for(int i=k;i;i--) inv[i-1] = inv[i] * i % mod;
 50 }
 51 inline lli c(int n,int m) {
 52     return fac[n] * inv[m] % mod * inv[n-m] % mod;
 53 }
 54 
 55 namespace Inter {
 56     lli fac[maxn],facrev[maxn],pprv[maxn],ssuf[maxn],*prv=pprv+1,*suf=ssuf+1;
 57     inline lli getmul(int p) {
 58         return p ? fac[p] * facrev[k-p-1] % mod : facrev[k-1];
 59     }
 60     inline lli getval(lli* in,lli x) {
 61         x %= mod;
 62         lli ret = 0;
 63         prv[-1] = 1;
 64         for(int i=0;i<k;i++) prv[i] = prv[i-1] * (x-i+mod) % mod;
 65         suf[k] = 1;
 66         for(int i=k-1;~i;i--) suf[i] = suf[i+1] * (x-i+mod) % mod;
 67         for(int i=0;i<k;i++) {
 68             lli now = prv[i-1] * suf[i+1] % mod;
 69             ret = ret + now * in[i] % mod * getmul(i) % mod , ret %= mod;
 70         }
 71         return ret;
 72     }
 73     inline void getinv() {
 74         static lli inv[maxn];
 75         *fac = 1;
 76         for(int i=1;i<=k;i++) fac[i] = fac[i-1] * i % mod;
 77         inv[k] = fastpow(fac[k],mod-2);
 78         for(int i=k;i;i--) inv[i-1] = inv[i] * i % mod;
 79         for(int i=1;i<=k;i++) inv[i] = inv[i] * fac[i-1] % mod;
 80         for(int i=1;i<=k;i++) fac[i] = fac[i-1] * inv[i] % mod;
 81         facrev[0] = 1;
 82         for(int i=1;i<=k;i++) facrev[i] = facrev[i-1] * ( mod - inv[i] ) % mod;
 83     }
 84 }
 85 
 86 inline void getg0() {
 87     static Node now;
 88     int mul = 1;
 89     for(int i=0;i<=k;i++) {
 90         now = now + ns[k-i] * ( mul == 1 ? c(k,i) : mod - c(k,i) );
 91         mul *= -1;
 92     }
 93     g[0] = ( mod - now.b ) % mod * fastpow(now.a,mod-2) % mod;
 94 }
 95 inline void calc() {
 96     const lli inv = fastpow(p,mod-2);
 97     ns[0] = (Node){1,0};
 98     for(int i=1;i<=k;i++) ns[i] = ( ns[i-1] + in[i-1] ) * inv;
 99     getg0();
100     for(int i=1;i<=k;i++) g[i] = ( g[i-1] + in[i-1] ) % mod * inv % mod;
101 }
102 
103 int main() {
104     static lli ans,n;
105     scanf("%lld%d%d",&n,&k,&p) , ++k;
106     for(int i=0;i<k;i++) scanf("%lld",in+i);
107     pre() , calc();
108     Inter::getinv();
109     ans = ( Inter::getval(g,n+1) * fastpow_lli(p,n+1) % mod - g[0] + mod ) % mod;
110     printf("%lld\n",ans);
111     return 0;
112 }
View Code


T3:


一个很不靠谱的构造题......
还有很不靠谱的题解......


不想改了,把标程丢上来吧......

  1 #include<bits/stdc++.h>
  2 #define lowbit(x) (x&(-x))
  3 #define N 16
  4 using namespace std;
  5 int size[2*N],l[2*N],r[2*N],a[N],n;
  6 double f[2*N][1<<N][N],fac[N];
  7 vector<int> vec[N];
  8 int ls[1<<N],ln,lg[1<<N];
  9 int bitcount(int s){int ans=0;while (s) {ans++;s-=lowbit(s);}return ans;}
 10 void dfs(int s)
 11 {
 12     if (!l[s]) {size[s]=1;return;}
 13     dfs(l[s]);dfs(r[s]);
 14     size[s]=size[l[s]]+size[r[s]];
 15 }
 16 int st[18],top;
 17 void gao(int now,int rem,int w)
 18 {
 19     if (now>top) {ls[++ln]=w;return;}
 20     if (top-now>=rem) gao(now+1,rem,w);
 21     if (rem) gao(now+1,rem-1,w+st[now]);
 22 }
 23 void search(int s,int sz)
 24 {
 25     top=0; 
 26     while (s)
 27     {
 28         st[++top]=lowbit(s);
 29         s-=lowbit(s);
 30     }
 31     gao(1,sz,0);
 32 }
 33 void work(int s)
 34 {
 35     if (!l[s])
 36     {
 37         for (int i=0;i<n;i++) f[s][1<<i][i]=1;
 38         return;
 39     }
 40     work(l[s]);work(r[s]);
 41     double pp=fac[size[l[s]]]*fac[size[r[s]]]/fac[size[s]];
 42     for (int k=0;k<vec[size[s]].size();k++)
 43     {
 44         int d=vec[size[s]][k];
 45         ln=0;search(d,size[l[s]]);
 46         for (int kk=1;kk<=ln;kk++)
 47         {
 48             int dd=ls[kk];
 49             for (int ii=dd,i=lg[lowbit(ii)];ii;ii-=lowbit(ii),i=lg[lowbit(ii)])
 50             for (int jj=d-dd,j=lg[lowbit(jj)];jj;jj-=lowbit(jj),j=lg[lowbit(jj)])
 51             {
 52                 double p=pp*f[l[s]][dd][i]*f[r[s]][d-dd][j]/(a[i]+a[j]);
 53                 f[s][d][i]+=p*a[i];
 54                 f[s][d][j]+=p*a[j];
 55             }
 56         }
 57     }
 58 }
 59 double zuo()
 60 {
 61     memset(f,0,sizeof(f));
 62     memset(size,0,sizeof(size));
 63     dfs(1);work(1);
 64     return f[1][(1<<n)-1][0];
 65 }
 66 int tp;
 67 int gen1(int n)
 68 {
 69     int s=++tp;
 70     if (n==1) {l[s]=r[s]=0;return s;}
 71     int dv=1;
 72     l[s]=gen1(dv);r[s]=gen1(n-dv);
 73     return s;
 74 }
 75 int gen2(int n)
 76 {
 77     int s=++tp;
 78     if (n==1) {l[s]=r[s]=0;return s;}
 79     int dv=n/2;
 80     l[s]=gen2(dv);r[s]=gen2(n-dv);
 81     return s;
 82 }
 83 int gen3(int n)
 84 {
 85     int s=++tp;
 86     if (n==1) {l[s]=r[s]=0;return s;}
 87     int dv=rand()%(n-1)+1;
 88     l[s]=gen3(dv);r[s]=gen3(n-dv);
 89     return s;
 90 }
 91 int main()
 92 {
 93     scanf("%d",&n);
 94     for (int i=0;i<=n;i++) lg[1<<i]=i;
 95     fac[0]=1;for (int i=1;i<=n;i++) fac[i]=fac[i-1]*i;
 96     for (int s=0;s<(1<<n);s++)
 97     {
 98         vec[bitcount(s)].push_back(s);
 99     }
100     for (int i=0;i<n;i++) scanf("%d",&a[i]);
101      
102     int ll=1,rr=100;
103     while (ll+1!=rr)
104     {
105         int mid=(ll+rr)>>1;a[0]=mid;
106         double p1,p2;
107         tp=0;gen1(n);p1=zuo();
108         tp=0;gen2(n);p2=zuo();
109         if (p1<p2) rr=mid;else ll=mid;
110     }
111     a[0]=ll;
112     double p1,p2,ans;
113     tp=0;gen1(n);p1=zuo();
114     tp=0;gen2(n);p2=zuo();
115     ans=max(p1,p2);
116     while (1)
117     {
118         tp=0;gen3(n);
119         if (zuo()>ans+1e-9)
120         {
121             printf("1\n1 %d\n",a[0]);
122             for (int i=1;i<=2*n+1;i++) printf("%d %d\n",l[i],r[i]);
123             return 0;
124         }
125     }
126 }
View Code

 

转载于:https://www.cnblogs.com/Cmd2001/p/8597413.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值