北京集训: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 }
写挂的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 */
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 }
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 }
修正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 }
正解代码:
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 }
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 }