Noip模拟51 2021.9.12
作者:互联网
T1 茅山道术
考场上卡在了一个恶心的地方,
当时以为每次施法都会产生新的可以施法的区间,然后想都没细想,
认为不可做,甚至$dfs$也无法打,考后一问发现是自己想多了。。
新产生的区间对答案根本没有贡献,还是可以按照原来的相同的颜色搞,
于是无论是$dfs$也好,$dp$也罢,都不用考虑新产生区间的后效性问题
那么我们设$dp_i$表示处理到第$i$个宝石,然后判断一下他的前面有无与他同色的宝石
转移维护前缀和即可。
1 #include<bits/stdc++.h>//分治+dp? 2 #define int long long 3 using namespace std; 4 namespace AE86{ 5 inline int read(){ 6 int x=0,f=1;char ch=getchar(); 7 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 8 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f; 9 }inline void write(int x,char opt='\n'){ 10 char ch[20];int len=0;if(x<0)x=~x+1,putchar('-'); 11 do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x); 12 for(register int i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt);} 13 }using namespace AE86; 14 15 const int NN=1e6+5,mod=1e9+7; 16 int n,tot,a[NN],pre[NN]; 17 namespace tree_array{ 18 int tr[NN]; 19 inline int lowbit(int x){return x&(-x);} 20 inline void update(int x,int v){for(int i=x;i<NN;i+=lowbit(i))(tr[i]+=v)%=mod;} 21 inline int query(int x){int ans=0;for(int i=x;i;i-=lowbit(i))(ans+=tr[i])%=mod;return ans;} 22 }using namespace tree_array; 23 24 namespace WSN{ 25 inline short main(){ 26 freopen("magic.in","r",stdin); 27 freopen("magic.out","w",stdout); 28 n=read(); 29 for(int i=1;i<=n;i++) a[i]=read(); 30 for(int i=1;i<=n;i++) 31 if(a[i]!=a[i-1]) a[++tot]=a[i]; 32 n=tot;update(1,1); 33 for(int i=1;i<=n;i++){ 34 if(pre[a[i]]) update(i,query(pre[a[i]])); 35 pre[a[i]]=i; 36 } 37 write(query(n)); 38 return 0; 39 } 40 } 41 signed main(){return WSN::main();}View Code
T2 泰拳警告
本场考试最大失误点
考场:
$woc$概率题,好像是$dp$,跳了跳了。。。
考后:
(看题解),啥?数学????
然后自己五分钟推柿子敲对了就$A$了
还是太弱,无法看出题型。。。太弱了。。。。
不难得出:
$ans= \sum_{i=0}^{n-1} (\frac{1}{p+2})^{n-i} *(\frac{p}{p+2})^i *(n+1) *\sum_{j=0}^{j=\frac{n-i}{2}} C_{n-i}^{j}$
然后发现后面的组合数加和可以轻松的使用杨辉三角每一行的对称性给它搞掉,就注意一下奇偶的细节即可
剩下的都能预处理,不预处理也可以卡过,只不过会拿最劣解(比如我)
1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 const int mod=998244353,NN=3e6+5; 5 namespace AE86{ 6 inline int read(){ 7 int x=0,f=1;char ch=getchar(); 8 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 9 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f; 10 }inline void write(int x,char opt='\n'){ 11 char ch[20];int len=0;if(x<0)x=~x+1,putchar('-'); 12 do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x); 13 for(register int i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt);} 14 inline int qmo(int a,int b){ 15 if(!a) return 1; 16 int ans=1,c=mod; a%=c; 17 while(b){ 18 if(b&1) ans=ans*a%c; 19 b>>=1; a=a*a%c; 20 } 21 return ans; 22 } 23 }using namespace AE86; 24 25 int n,p,inv,ans,v2,tmp,res; 26 int h[NN],v[NN],mi[NN],p1[NN],p2[NN]; 27 inline void pre(){ 28 h[0]=h[1]=1; v[0]=v[1]=1; mi[0]=p1[0]=p2[0]=1; 29 for(int i=2;i<NN;i++) h[i]=h[i-1]*i%mod; 30 v[NN-1]=qmo(h[NN-1],mod-2); 31 for(int i=NN-2;i>=2;i--) v[i]=v[i+1]*(i+1)%mod; 32 for(int i=1;i<=n;i++){ 33 mi[i]=mi[i-1]*2%mod; 34 p1[i]=p1[i-1]*p%mod*inv%mod; 35 p2[i]=p2[i-1]*inv%mod; 36 } 37 } 38 inline int C(int n,int m){ 39 if(n<m||n<0||m<0) return 0; 40 return h[n]*v[n-m]%mod*v[m]%mod; 41 } 42 43 namespace WSN{ 44 inline short main(){ 45 freopen("fight.in","r",stdin); 46 freopen("fight.out","w",stdout); 47 n=read(); p=read(); inv=qmo(p+2,mod-2); v2=qmo(2,mod-2); 48 pre(); 49 for(int i=0;i<n;++i){ 50 tmp=p1[i]*(i+1)%mod*p2[n-i]%mod*C(n,i)%mod; 51 if((n-i)&1){ 52 res=mi[n-i]*v2%mod; 53 ans=(ans+tmp*res%mod)%mod; 54 } 55 else{ 56 res=(mi[n-i]-C(n-i,(n-i)/2)+mod)%mod*v2%mod; 57 ans=(ans+tmp*res%mod)%mod; 58 } 59 } 60 write(ans); 61 return 0; 62 } 63 } 64 signed main(){return WSN::main();}View Code
T3 万猪拱塔
$sb$细节题
考虑枚举权值$[l,r]$的一段区间,将编号在这一段的格子染黑,然后判断黑色是否可以构成一个矩形
我们可以搞出来$(n+1)*(m+1)$ 个$2*2$的小方块覆盖整个矩阵(在边缘外的也算),可以发现:
能够成一个矩形,当且仅当 有$4$个小方块只覆盖$1$个黑格子,没有小方块覆盖恰好$3$个黑格子
要维护$2*2$的小方块:
记$kua[i][5]$为编号为$i$的小方块里面四个格子的权值,因为枚举权值区间的过程是单调递增的
所以将块内的权值排序,这就是他们被染色的顺序,然后按照顺序依次在线段树上$+1,-1$操作即可
设$f(l)$表示在$[l,r]$区间内有多少个小方块包含$1$个或$3$个黑格子,
线段树上维护: $f(l)$的最小值,最小值数目,以及造成最小值的$l$的和。
刚才维护小方块所说的操作就是对最小值的操作
那么最后的答案可以通过维护的值算出。
标签:ch,NN,2021.9,namespace,ans,51,int,12,小方块 来源: https://www.cnblogs.com/hzoi-wsn/p/15264579.html