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

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

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

$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 ightarrow C$这一段弧是一个优弧,至少跨过$frac{n}{2}$个点。

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

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

首先三角形的确可能有解。不是三角形的话则需要有三个$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$是几。总方案是$sumlimits_{a_4=N+3}^{n} inom{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$。方案数就是$inom{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
",cal3(n,m));
24         else if(k==2)printf("%d
",cal2(n,m));
25         else if(k==1)printf("%d
",cal1(n,m));
26         else printf("%lld
",(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 imes 10^5$

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

所以直接开一个$unordered-set$暴力维护子树中所有点的权值及出现次数,复杂度$O(nsqrt{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
",ans);
33 }
View Code

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

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

T3:多项式

大意:有$n$个$0 <xle 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++$

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

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

$n^{underline{m}} = sumlimits_{i=0}^{m} (-1)^{m-i} egin{bmatrix} m \ iend{bmatrix} n^i$

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

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

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

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

$A_j = sumlimits_{sumlimits_{i=1}^{n} a_i = x} x^j$

设$F_{k,j} = sumlimits_{sumlimits_{i=1}^{k} a_i = x} x^j$

根据二项式展开那一套,有$F_{x+y,i+j} = sum F_{x,i} F(y,j) inom{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
",ans*1ll*qp(fac[m],mod-2)%mod);
27 }
View Code
原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/12891822.html