ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

21杭电多校第五场

2021-08-04 10:34:38  阅读:194  来源: 互联网

标签:杭电多校 ch 21 int 第五场 sum long MOD define


A

LCT 咕

B

单位根反演 弃了

C

大胆猜测当\(n>k+1\)时无解

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b)+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
ll n,k;
int main()
{
	rep(T,1,read())
	{
		n=read(),k=read();
		puts(n>k+1?"No":"Yes");
	}
}

E

将对角线处的转移矩阵记为\(B\),将原转移矩阵的对角线赋值为\(0\)记为\(A\)

由定义出发,最终答案矩阵为$I\sum\limits_{i=0}{\infty}AiB $,其中左侧的单位矩阵对应初始条件

则$Ans=(\sum\limits_{i=0}{\infty}Ai)B=\frac{A{\infty}-I}{A-I}B=(A{\infty}-I)(A-I)^{-1}B $

由于\(A^{\infty}=\mathbf{0}\),则$Ans=-(A-I)^{-1}B \(,因此只需要对\)(A-I)$矩阵求逆

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b)+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,a[350][350],p[350][700],sum[350],res[350][350];
void inc(int &x,int a) {x=pls(x,a);}
void dec(int &x,int a) {x=mns(x,a);}
void tms(int &x,int a) {x=mul(x,a);}
int inv(int bas,int res=1)
{
    for(int t=MOD-2;t;t>>=1,bas=mul(bas,bas))
        if(t&1) res=mul(res,bas);return res;
}
void mat_inv(int n)
{
	int t,pos;rep(i,1,n)
	{
		pos=-1;rep(j,i,n) if(p[j][i]) {pos=j;break;}
		if(pos==-1) return ;
		swap(p[i],p[pos]);t=inv(p[i][i]);
		rep(j,i,n<<1) tms(p[i][j],t);
		rep(j,i+1,n) dwn(k,n<<1,i) dec(p[j][k],mul(p[i][k],p[j][i]));
	}
	dwn(i,n,1) rep(j,1,i-1) dwn(k,n<<1,i) dec(p[j][k],mul(p[i][k],p[j][i]));
}
int main()
{
	rep(T,1,read())
	{
		n=read();rep(i,1,n) sum[i]=0;
		rep(i,1,n) rep(j,1,n) p[i][j]=read(),p[i][j+n]=0,inc(sum[i],p[i][j]);
		rep(i,1,n) sum[i]=inv(sum[i]);
		rep(i,1,n) rep(j,1,n) tms(p[i][j],sum[i]);
		rep(i,1,n) a[i][i]=p[i][i],p[i][i]=MOD-1,p[i][i+n]=1;
		mat_inv(n);
		rep(i,1,n) rep(j,1,n)
		{
			res[i][j]=0;
			rep(k,1,n) dec(res[i][j],mul(p[i][k+n],a[k][j]));
		}
		rep(i,1,n) rep(j,1,n) printf("%d%c",res[i][j],j==n?'\n':' ');
	}
}

F

签到题,直接按题意模拟建树操作

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 200100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b)+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,a[MAXN],ans;
void solve(int l,int r)
{
	ans++;if(l==r) return ;if(r-l==1) {ans+=2;return ;}
	int ml=l+(r-l+2)/3-1,mr=(ml+r)/2;
	solve(l,ml);solve(ml+1,mr);solve(mr+1,r);
}
int main()
{
	rep(T,1,read())
	{
		ans=0;n=read();rep(i,1,n) a[i]=read();
		solve(1,n);printf("%d\n",ans);
	}
}

G

对于最小值,铺满最下面一层和\(xOz\)、\(yOz\)平面,其中\(z\)轴不需要

对于最大值,从最高处掉\(n\)次

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 1000000007
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b)+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline ll read()
{
	ll x=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
ll n;int ans,s1,s2;
void inc(int &x,int a) {x=pls(x,a);}
int qp(int x,int t,int res=1)
{
    for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(x,res);
	return res;
}
#define inv(x) qp(x,MOD-2)
const int inv2=inv(2),inv6=inv(6);
int sum(int x){return mul(mul(x,x+1),inv2);}
int sum2(int x){return mul(mul(x,x+1),mul(2*x+1,inv6));}
int main()
{
	rep(T,1,read())
	{
		n=read();n%=MOD,s1=sum(n),s2=sum2(n);
		ans=mul(s1,s2);
		inc(ans,mul(s1-1,s1-1));
		inc(ans,mul(s1-1,s2-1));
		printf("%lld\n",ans);ans=0;
		ans=mul(s1,s2);ans=mul(ans,mul(n,n));
		printf("%lld\n",ans);
	}
}

H

根据条件概率公式,答案可以转化为

\[\sum\limits_{S\in[0,2^n)}\sum\limits_{T\in[0,2^n)}\frac{\sum_{S\subseteq A_i,T\subseteq A_i} 1}{\sum_{S\subseteq A_i} 1} \]

记\(sum[S]\)表示\(S\)的超集数量即\(sum[S]=\sum\limits_{S\subseteq A_i}1\),则\(Ans=\sum\limits_{S\in[0,2^n)}\sum\limits_{T\in[0,2^n)}\frac{sum[S \cup T]}{sum[S]}\)

而显然有\(S\subseteq\{S\cup T\}\),令\(sum2[S]=\sum\limits_{S\subseteq T}sum[T]\),对每个\(S\cup T\)显然有\(2^{bit[S]}\)个\(T\)使得\(S\cup T\)相同

因此\(Ans=\sum\limits_{S\in[0,2^n)}\frac{sum2[S]\cdot 2^{bit[S]}}{sum[S]}\),这两个求高位前缀和的过程可以使用\(fwt\)便利解决

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 2001001
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b)+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int s[MAXN],s2[MAXN],bit[MAXN],ans,n,m,mxs;
int qp(int x,int t,int res=1)
{
    for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(x,res);
	return res;
}
void fwt(int *a,int n)
{
	for(int i=1;i<n;i<<=1) for(int j=0;j<n;j+=i<<1) rep(k,0,i-1)
		a[j+k]+=a[j+k+i];
}
int main()
{
	rep(T,1,read())
	{
		n=read(),m=read(),mxs=(1<<n)-1,ans=0;int res;
		rep(i,0,mxs) s[i]=s2[i]=0,bit[i]=i?bit[i-(i&-i)]+1:0;
		rep(i,1,m) s[read()]++;fwt(s,1<<n);
		rep(i,0,mxs) s2[i]=s[i];fwt(s2,1<<n);
		rep(i,0,mxs)
		{
			res=qp(s[i],MOD-2,s2[i]);
			ans=pls(ans,mul(res,1<<bit[i]));
		}
		printf("%d\n",ans);
	}
}

I

和一道原来的题一样,但线段树维护一次函数直接\(T\)飞了

先枚举那个众数\(x\),令\(sum_i=sum_{i-1}+(a_i==x?1:-1)\)

则对于每个\((i,sum_i)\),答案即为满足\(j<i,sum_j<sum_i\)的\(j\)的个数

直接加入每个点显然复杂度过高,而上升点的总数为\(n\)

考虑如何快速维护一段下降的贡献,对于\(sum\)值进行差分,则所求即为这个差分数组的二阶前缀和

image

对于这样一个图像,我们对于红线上方的点暴力维护差分数组以及差分数组的一二阶前缀和用来统计答案,而红线到下一次最小值之间的点并不会作为右端点对答案有贡献,因此我们可以暴力计算所有红线上方点的贡献

#include<bits/stdc++.h>
#define rep(i,s,t) for(int i=(s),i__end=(t);i<=i__end;++i)
#define dwn(i,s,t) for(int i=(s),i__end=(t);i>=i__end;++i)
#define ren(x) for(register int i=fst[x];i;i=nxt[i])
#define pb(a,x) vec[a].push_back(x);
#define ll long long
#define inf 2139062143
#define MAXN 1001001
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,g[MAXN],hsh[MAXN],m,del[MAXN<<2],tp,tag[MAXN<<1];
ll sum,ans,now,tot;int mn;
vector<int> vec[MAXN];
void work(int id)
{
	pb(id,n+1);//cout<<id<<"\n";
	del[1]=0,del[tp=2]=1;tag[0+n]++,tag[1+n]--;
	mn=sum=now=0,tot=1;int las=0,lim;
	for(auto x:vec[id])
	{
		//cout<<x<<" "<<now<<" "<<tot<<" "<<sum<<" "<<ans<<endl;
		if(x!=las+1)
		{
			int tmp=now;
			for(lim=now-(x-las)+1;now>max(lim,mn);now--)
				tot-=tag[now+n],sum-=tot,ans+=sum;
			//cout<<lim<<" "<<mn<<" "<<now<<endl;
			if(mn>lim) mn=now=lim,tot=0,sum=0;
			tot++;del[++tp]=now,tag[now+n]++;
			del[++tp]=tmp,tag[tmp+n]--;
		}
		if(x==n+1) break;
		sum+=tot,ans+=sum;
		now++,del[++tp]=now,tag[now+n]++,del[++tp]=now+1,tag[now+1+n]--;
		tot+=tag[now+n],las=x;
		//cout<<x<<" "<<now<<" "<<tot<<" "<<sum<<" "<<ans<<endl;
	}
	while(tp) tag[del[tp]+n]=0,tp--;
}
int main()
{
	rep(T,1,read())
	{
    	n=read();rep(i,1,n) {g[i]=read();if(!hsh[g[i]]) hsh[g[i]]=++m;}
    	rep(i,1,n) pb(hsh[g[i]],i);
    	rep(i,1,m) work(i);printf("%lld\n",ans);
    	rep(i,1,n) hsh[g[i]]=0;rep(i,1,m) vec[i].clear();m=0;ans=0;
    }
}

J

概率论 不会

K

奇怪的博弈 咕

L

生成函数,多项式快速幂 咕

M

标签:杭电多校,ch,21,int,第五场,sum,long,MOD,define
来源: https://www.cnblogs.com/yyc-jack-0920/p/15097686.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有