码迷,mamicode.com
首页 > 其他好文 > 详细

[考试反思]0514省选模拟96:对比

时间:2020-05-15 09:56:00      阅读:61      评论:0      收藏:0      [点我收藏+]

标签:方便   cli   open   圆心   mamicode   clear   组合   include   抽象   

技术图片

技术图片

来了。又是越考越差的时段。

和昨天是一个出题人,心态先崩一半。

$T1$有了点部分分剩下的还是没有。依然没有构造。依然出现原题($T3$是仓鼠杂题2)

然后比昨天还毒瘤的是今天连大样例都没了。

今天把联考的排行榜粘过来以彰显自己有多菜。

今天主要是时间分配挂了。

$T1$写了三小时半多,$T2$用了$17min$,$T3$用了$10min$。然后浏览器被$oj$卡死提交用了$20min$。剩下时间在摸鱼(放弃挣扎

$T1$最后会正解了但是来不及细想了(因为$T2,3$暴力没打)所以剩下$20$分不要就不要了。

考场上大规模干$T1$就是脑子有问题。(大分类讨论玩得挺欢?

$T2$写了个乱搞本来能过$50$然后因为分配的时间太少写着急了有一个细节挂掉直接就爆零了。(我还以为样例不水)

全世界都没几个爆零的。。。

$T3$原题数学题。没时间了所以打暴力跑路了。结果居然是全场$AC$数最多的题。。

什么乱七八糟的。。。

 

T1:多边形

大意:求正$n$边形选$m$点构成的多边形恰有$k$锐角的方案数。$n$是奇数。$n \le 10^6,T \le 10^5$

$k>3$无解。

考虑:多边形外角和为$360$。一个锐角对应一个$>90$的外角,故最多$3$个。

我们抽象一下问题:我们要选择$m$个点$1 \le a_1 <a_2 < ... <a_m <n$。满足恰有$k$个$i$满足$a_{i+2}-a_i > \frac{n}{2}$

(序列是循环的,也就是$a_{m+1}=a_1,a+{m+3}=a_2$)

考虑为什么:首先作出原多边形的外接圆,一个你选定的多边形的角$ABC$也就是一个圆周角,则它对应的圆心角是二倍圆周角。

圆周角是锐角所以圆心角小于平角。所以说$a \rightarrow C$这一段弧是一个优弧,至少跨过$\frac{n}{2}$个点。

为了方便下面设$N=\frac{n}{2}$

$k=3$时一定是三角形。此时$m \neq$则无解。

首先三角形的确可能有解。不是三角形的话则需要有三个$i$满足条件,至少有两个$i$的奇偶性相同。

$a_i < a_{i+2} < a_{i+2x} < a_{i+2x+2}$。第$1,3$个小于号的跨度都是$N$。所以$a_{i+2x+2}-a_i>n$就直接非法了。

然后一定是三角形的话,我们固定其中一个点,枚举第二个点的编号,发现第三个点可选位置数是等差数列。直接$O(1)$解决。

$k=2$的话满足条件的两个$i$相差一定是$1$如果差距更大的话可以同上得到总长过长而非法。

我们钦定其中一个$i=1,a_1=1$。计算此时的方案再通过旋转得到其它所有方案。

我们去枚举$a_4$是几。总方案是$\sum\limits_{a_4=N+3}^{n} \binom{n-a_4}{m-4} (a_4-N-2)^2$

就是后边的点随便选,那个平方就是在$a_1,a_4$之间选择$a_2,a_3$的方案数。

考虑组合含义优化:我们在$[N+2,n]$里选择$a_4$,$n-a_4$个元需里选$m-2$个,再在$a_4-N-2$个元素里可重复选两个。

分类讨论你可重复选的那两个是否重复了:

重复那就是一共在$[N+2,n]$里随便选$m-3$个然后钦定其中第二个是$a_4$。方案一一对应。直接组合数。

不重复那就多选一个,考虑到顺序问题还要乘$2$。

特殊处理$m=3$。这样$k=2$就可以$O(1)$解决。

$k=1$的话我采用的方法是:计数所有多边形的锐角个数和再减去$k \ge 2$的方案的贡献。

所以我们再次钦定一个锐角$i=1,a_1=1$。

这回只需要枚举$a_3 > N+1$。方案数就是$\binom{n-a_3}{m-3} (a_3-2)$

还是组合含义优化,分类讨论$a_2 >N+1$与否,组合数加上组合数乘系数。

$k=0$的情况就是所有情况减去上边这些情况。

总时间复杂度$O(n+T)$

技术图片
 1 #include<cstdio>
 2 const int mod=1000109107,S=1000005;
 3 int qp(int b,int t,int a=1){for(;t;t>>=1,b=1ll*b*b%mod)if(t&1)a=1ll*a*b%mod;return a;}
 4 int n,m,t,k,fac[S],inv[S];
 5 int C(int b,int t){return t<0||t>b?0:fac[b]*1ll*inv[t]%mod*inv[b-t]%mod;}
 6 int cal3(int n,int m){return m==3?n*(n+1ll)*(2*n+1)/6%mod:0;}
 7 int cal2(int n,int m){
 8     if(m==3)return (mod+C(n+n+1,3)-cal3(n,m))%mod;
 9     return (2ll*C(n,m-1)+C(n,m-2))*(1ll+n+n)%mod;
10 }
11 int cal1(int n,int m){
12     int ans=(C(n,m-2)*1ll*n+C(n,m-1))%mod;
13     return ((ans*(1ll+n+n)-2*cal2(n,m)%mod-3ll*cal3(n,m))%mod+mod)%mod;
14 }
15 int main(){
16     for(int i=fac[0]=1;i<S;++i)fac[i]=fac[i-1]*1ll*i%mod;
17     inv[S-1]=qp(fac[S-1],mod-2);
18     for(int i=S-2;~i;--i)inv[i]=inv[i+1]*(i+1ll)%mod;
19     scanf("%d",&t);while(t--){
20         scanf("%d%d%d",&n,&m,&k);
21         n>>=1;
22         if(k>3)puts("0");
23         else if(k==3)printf("%d\n",cal3(n,m));
24         else if(k==2)printf("%d\n",cal2(n,m));
25         else if(k==1)printf("%d\n",cal1(n,m));
26         else printf("%lld\n",(mod*3ll+C(n+n+1,m)-cal1(n,m)-cal2(n,m)-cal3(n,m))%mod);
27     }
28 }
View Code

 

T2:仙人掌

大意:树,每次操作会使某个点所有邻居权值$+1$并询问所有邻居权值异或和。$n,Q \le 5 \times 10^5$

每次$+1$的话那么子树里所有节点的权值最多有$O(\sqrt{m})$种。

所以直接开一个$unordered-set$暴力维护子树中所有点的权值及出现次数,复杂度$O(n\sqrt{n})$

技术图片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define f1 first
 4 #define s2 second
 5 const int mod=1000109107,S=1000005;
 6 int n,m,ans,fir[S],l[S],to[S],ec,f[S],ts[S],tf[S];
 7 unordered_map<int,int>M[S],R;
 8 void link(int a,int b){l[++ec]=fir[a];fir[a]=ec;to[ec]=b;}
 9 void dfs(int p,int fa){
10     f[p]=fa; M[fa][0]++;
11     for(int i=fir[p];i;i=l[i])if(to[i]!=fa)dfs(to[i],p);
12 }
13 int addson(int p){
14     int a=0;
15     for(auto x:M[p])R[x.f1+1]=x.s2,a^=x.s2&1?x.f1+1:0;
16     swap(M[p],R);R.clear(); return a;
17 }
18 int addfa(int p){
19     if(!p)return 0;
20     int a=tf[p]+ts[f[p]];
21     int&x=M[f[p]][a];x--; if(!x)M[f[p]].erase(M[f[p]].find(a));
22     M[f[p]][a+1]++; return a+1;
23 }
24 int main(){
25     scanf("%d%d",&n,&m);
26     for(int i=1,a,b;i<n;++i)scanf("%d%d",&a,&b),link(a,b),link(b,a);
27     dfs(1,0);
28     for(int _=1,x;_<=m;++_)
29         scanf("%d",&x),
30         ans=(ans+(1ll*_*_+_)%mod*(addson(x)^addfa(f[x])))%mod,
31         ts[x]++,tf[f[x]]++;
32     printf("%d\n",ans);
33 }
View Code

正解是,发现一个数$+1$相当与异或上$2^{z+1}-1$。$z$是最低的$0$位。

按从低位到高位维护$trie$表示儿子的所有权值。每次跑$1$方向修改并更新答案。$O(nlogn)$

 

T3:多项式

大意:有$n$个$0 <x\le T$的变量和$m$个$0<x$的变量,其和$\le S$。求方案数。$n \le 10^9,m \le 10^3,nT \le S \le 10^{18},T \le 10^9$

首先为了方便去掉$\le S$的限制所以我们可以新增一个不限制的变量,也就是说$m++$。为了让它也满足$x>0$需要让$S++$

可以列出这样一个基础式子$\sum\limits_{x_{1...n},\sum a =x} \binom{S-x}{m}$

组合数化成下降幂除阶乘,阶乘可以拿出来单算。然后我们有

$n^{\underline{m}} = \sum\limits_{i=0}^{m} (-1)^{m-i} \begin{bmatrix} m \\ i\end{bmatrix} n^i$

也就有我们要求的是$\frac{1}{m!} \sum\limits_{\sum a_i = x} \sum\limits_{i=0}^{m} \begin{bmatrix} m \\ i \end{bmatrix}  (-1)^{m-i} (S-x)^i$

最后那个东西二项式展开一下

$\frac{1}{m!} \sum\limits_{\sum a_i = x} \sum\limits_{i=0}^{m} \begin{bmatrix} m \\ i \end{bmatrix}  (-1)^{m-i} \sum\limits_{j=0}^{i} S^{i-j}(-1)^j x^j$

这样就只有最后一项与$x$有关了。我们要求的形如下式:

$A_j = \sum\limits_{\sum\limits_{i=1}^{n} a_i = x} x^j$

设$F_{k,j} = \sum\limits_{\sum\limits_{i=1}^{k} a_i = x} x^j$

根据二项式展开那一套,有$F_{x+y,i+j} = \sum F_{x,i} F(y,j) \binom{i+j}{i}$

所以可以直接倍增$F$求出$A$。$F_{0,i}$就是简单的自然数幂和。随便怎么做都行。

式子逐层处理即可。时间复杂度$O(m^2logn)$

技术图片
 1 #include<cstdio>
 2 #define ll long long
 3 const int mod=1000109107,S=1005;
 4 int n,m,t,fac[S],ans,F[31][S],A[S],st[S][S],St[S][S],C[S][S],iv[S],G[S],pws[S];ll s;
 5 int qp(int b,int t,int a=1){for(;t;t>>=1,b=1ll*b*b%mod)if(t&1)a=1ll*a*b%mod;return a;}
 6 int Spw(int n,int k,int a=0){for(int i=0,C=1+n;i<=k;++i)a=(a+1ll*St[k][i]*fac[i]%mod*C)%mod,C=1ll*C*(n-i)%mod*iv[i+2]%mod;return a;}
 7 int main(){
 8     for(int i=fac[0]=iv[1]=1;i<S;++i)fac[i]=fac[i-1]*1ll*i%mod;
 9     for(int i=2;i<S;++i)iv[i]=mod-mod/i*1ll*iv[mod%i]%mod;
10     for(int i=st[0][0]=St[0][0]=C[0][0]=1;i<S;++i)for(int j=C[i][0]=1;j<=i;++j)
11         st[i][j]=(st[i-1][j]*(i-1ll)+st[i-1][j-1])%mod,
12         St[i][j]=(St[i-1][j]*1ll*j+St[i-1][j-1])%mod,
13         C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
14     scanf("%lld%d%d%d",&s,&t,&n,&m); m-=n; s%=mod;
15     for(int i=0;i<=m;++i)F[0][i]=Spw(t,i); F[0][0]--;
16     for(int i=1;1<<i<=n;++i)for(int j=0;j<=m;++j)for(int k=0;k+j<=m;++k)
17         F[i][j+k]=(F[i][j+k]+1ll*F[i-1][j]*F[i-1][k]%mod*C[j+k][j])%mod;
18     for(int i=0;i<=30;++i)F[i][0]--;
19     A[0]=1;
20     for(int i=0;1<<i<=n;++i)if(n>>i&1)for(int j=m;~j;--j)for(int k=m-j;~k;--k)
21         A[j+k]=(A[j+k]+1ll*A[j]*F[i][k]%mod*C[j+k][j])%mod;
22     for(int i=pws[0]=1;i<=m;++i)pws[i]=pws[i-1]*1ll*s%mod;
23     for(int i=0;i<=m;++i)for(int j=0;j<=i;++j)
24         G[i]=(G[i]+(j&1?mod-1ll:1ll)*pws[i-j]%mod*A[j]%mod*C[i][j])%mod;
25     for(int i=0;i<=m;++i)ans=(ans+(m-i&1?mod-1ll:1ll)*st[m][i]%mod*G[i])%mod;
26     printf("%lld\n",ans*1ll*qp(fac[m],mod-2)%mod);
27 }
View Code

 

[考试反思]0514省选模拟96:对比

标签:方便   cli   open   圆心   mamicode   clear   组合   include   抽象   

原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/12891822.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!