九下三月上旬日记

3.1

闲话

做题纪要

luogu B3908 [语言月赛 202312] 异或构造题?

  • 构造 \(x= \bigoplus\limits_{i=1}^{n}a_{i}\) 即可。

    点击查看代码
    int main()
    {
    	ll n,a,x=0,i;
    	cin>>n;
    	for(i=1;i<=n;i++)
    	{
    		cin>>a;
    		x^=a;
    	}
    	cout<<x<<" "<<0<<endl;
    	return 0;
    }
    

luogu P4303 [AHOI2006] 基因匹配

  • \(f_{i,j}\) 表示 \(S1\) 的前 \(i\) 位, \(S2\) 的前 \(j\) 位的 \(LCS\) 的长度,状态转移方程为 \(f_{i,j}=\begin{cases}\max(f_{i-1,j},f_{i,j-1}) & S1_{i} \ne S2_{j} \\ \max(f_{i-1,j},f_{i,j-1},f_{i-1,j-1}+1) & S1_{i}=S2_{j} \end{cases}\)

  • 类似用 luogu P3531 [POI2012] LIT-Letters 的思想去把 \(LCS\) 转化为 \(LIS\) 问题。

    • 具体地,对于 \(S1\)\(S2\) 的任意公共子序列 \(S=s_{1}s_{2} \dots s_{k}\) ,设 \(s_{i}\)\(S1\) 中第一次出现的位置为 \(a_{i}\) ,在 \(S2\) 中第一次出现的位置为 \(b_{i}\) ,则对于任意 \(i(1<i \le k)\) 恒有 \(a_{i}>a_{i- 1},b_{i}>b_{i-1}\) ,故就转化为了二维偏序问题。在枚举 \(S2\) 的过程中 \(b\) 之间的大小关系已经满足偏序,然后用树状数组或二分维护 \(a\)\(LIS\) 即可。
  • 注意状态转移没有后效性。

    点击查看代码
    int c[200000],f[200000],a[200000],b[200000];
    vector<int>vis[200000];
    int lowbit(int x)
    {
    	return (x&(-x));
    }
    void add(int n,int x,int key)
    {
    	for(int i=x;i<=n;i+=lowbit(i))
    	{
    		c[i]=max(c[i],key);
    	}
    }
    int getsum(int x)
    {
    	int ans=0;
    	for(int i=x;i>=1;i-=lowbit(i))
    	{
    		ans=max(ans,c[i]);
    	}
    	return ans;
    }
    int main()
    {
    	int n,ans=0,i,j;
    	cin>>n;
    	for(i=1;i<=5*n;i++)
    	{
    		cin>>a[i];
    		vis[a[i]].push_back(i);
    	}
    	for(i=1;i<=5*n;i++)
    	{
    		cin>>b[i];
    	}
    	for(i=1;i<=5*n;i++)
    	{
    		if(vis[b[i]].size()>=1)
    		{
    			for(j=vis[b[i]].size()-1;j>=0;j--)
    			{
    				f[vis[b[i]][j]]=getsum(vis[b[i]][j]-1)+1;
    				add(5*n,vis[b[i]][j],f[vis[b[i]][j]]);
    			}
    		}
    	}
    	for(i=1;i<=5*n;i++)
    	{
    		ans=max(ans,f[i]);
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    

3.2

闲话

做题纪要

luogu P5142 区间方差

  • 对方差的推导过程详见 2.20 做题纪要 luogu P1471 方差

    点击查看代码
    const ll p=1000000007;
    ll a[500000];
    struct SegmentTree
    {
    	ll l,r,sum1,sum2;
    }tree[500000];
    ll lson(ll x)
    {
    	return x*2;
    }
    ll rson(ll x)
    {
    	return x*2+1;	
    }
    void pushup(ll rt)
    {
    	tree[rt].sum1=(tree[lson(rt)].sum1+tree[rson(rt)].sum1)%p;
    	tree[rt].sum2=(tree[lson(rt)].sum2+tree[rson(rt)].sum2)%p;
    }
    void build(ll rt,ll l,ll r)
    {
    	tree[rt].l=l;
    	tree[rt].r=r;
    	if(l==r)
    	{
    		tree[rt].sum1=a[l];
    		tree[rt].sum2=a[l]*a[l]%p;
    		return;
    	}
    	ll mid=(l+r)/2;
    	build(lson(rt),l,mid);
    	build(rson(rt),mid+1,r);
    	pushup(rt);
    }
    void update(ll rt,ll pos,ll val)
    {
    	if(tree[rt].l==tree[rt].r)
    	{
    		tree[rt].sum1=val;
    		tree[rt].sum2=val*val%p;
    		return;
    	}
    	ll mid=(tree[rt].l+tree[rt].r)/2;
    	if(pos<=mid)
    	{
    		update(lson(rt),pos,val);
    	}
    	else
    	{
    		update(rson(rt),pos,val);
    	}
    	pushup(rt);
    }
    ll query1(ll rt,ll l,ll r)
    {
    	if(r<tree[rt].l||tree[rt].r<l)
    	{
    		return 0;
    	}
    	if(l<=tree[rt].l&&tree[rt].r<=r)
    	{
    		return tree[rt].sum1;
    	}
    	return (query1(lson(rt),l,r)+query1(rson(rt),l,r))%p;
    }
    ll query2(ll rt,ll l,ll r)
    {
    	if(r<tree[rt].l||tree[rt].r<l)
    	{
    		return 0;
    	}
    	if(l<=tree[rt].l&&tree[rt].r<=r)
    	{
    		return tree[rt].sum2;
    	}
    	return (query2(lson(rt),l,r)+query2(rson(rt),l,r))%p;
    }
    ll qpow(ll a,ll b,ll p)
    {
    	ll ans=1;
    	while(b>0)
    	{
    		if(b&1)
    		{
    			ans=ans*a%p;
    		}
    		b>>=1;
    		a=a*a%p;
    	}
    	return ans;
    }
    int main()
    {
    	ll n,m,x,y,pd,sum1,sum2,i;
    	cin>>n>>m;
    	for(i=1;i<=n;i++)
    	{
    		cin>>a[i];
    	}
    	build(1,1,n);
    	for(i=1;i<=m;i++)
    	{
    		cin>>pd>>x>>y;
    		if(pd==1)
    		{
    			update(1,x,y);
    		}
    		if(pd==2)
    		{
    			sum1=query1(1,x,y)*qpow(y-x+1,p-2,p)%p;
    			sum2=query2(1,x,y)*qpow(y-x+1,p-2,p)%p;
    			cout<<(sum2-sum1*sum1%p+p)%p<<endl;
    		}
    	}
    	return 0;
    }
    

3.3

闲话

做题纪要

AT_joig2021_d 展覧会 2 (Exhibition 2)

3.4

闲话

  • 上午上正课的时候,感觉讲的好快,有点跟不上了。
  • 下午刚到机房的时候,有只鸽子飞进了 \(1\) 机房,找 \(miaomiao\) 说要把鸽子放出去了但没成功。后来 \(feifei\) 来了后联合机房众人把鸽子放出去了。
  • \(miaomiao\) 又稍微解释了下直升的政策,包括但不限于分校区时因怕和 @5k_sync_closer@hh弟中弟 等抢明年省队名额故不给分到 HZ 然后两个校区平分;若没考到衡中系自主招生线则必须学奥赛,学费看实际奥赛成绩。然后扯了些别的,包括但不限于因学校师资紧张,年级部不给安排上高一课程;初三下半年重心要放在奥赛上。
  • \(miaomiao\) 问我们身份证是否都在身上,在宿舍的赶紧回去拿,说报名中考要用。然后我就和没拿饭卡的 @CuFeO4 回宿舍去取了。
  • 晚上让填体育中考卷子,颇具形式主义。

做题纪要

luogu P3451 [POI2007]ATR-Tourist Attractions

  • \(d+1\)\(dijkstra\) ,分别预处理出从 \(1 \sim d+1\)\(1 \sim d+1\)\(n\) 的最短距离。

  • \(f_{i,j}\) 表示当前“停留状态”对应的二进制数为 \(i\) 时,且当前处于点 \(j\) 时的最短路长度。

  • 接下来考虑优化空间。

    • \(2 \sim d+1\) 映射到 \(0 \sim d-1\)
    • 因在转移过程中若 \(f_{i,j}\) 能进行转移则,则状态 \(i\) 中已经包含了 \(j\) ,故可以抹去这一位。
    点击查看代码
    struct node
    {
    	int nxt,to,w;
    }e[400010];
    int head[20010],dis[30][20010],viss[20010],f[(1<<19)+10][22],cnt=0;
    bool vis[20010];
    void add(int u,int v,int w)
    {
    	cnt++;
    	e[cnt].nxt=head[u];
    	e[cnt].to=v;
    	e[cnt].w=w;
    	head[u]=cnt;
    }
    void dijkstra(int s)
    {
    	memset(dis[s],0x3f,sizeof(dis[s]));
    	memset(vis,false,sizeof(vis));
    	priority_queue<pair<int,int> >q;
    	int x,i;
    	dis[s][s]=0;
    	q.push(make_pair(0,-s));
    	while(q.empty()==0)
    	{
    		x=-q.top().second;
    		q.pop();
    		if(vis[x]==false)
    		{
    			vis[x]=true;
    			for(i=head[x];i!=0;i=e[i].nxt)
    			{
    				if(dis[s][e[i].to]>dis[s][x]+e[i].w)
    				{
    					dis[s][e[i].to]=dis[s][x]+e[i].w;
    					q.push(make_pair(-dis[s][e[i].to],-e[i].to));
    				}
    			}
    		}
    	}
    }
    int del(int x,int y)
    {     
    	return ((x>>(y+1))<<y)+x-((x>>y)<<y);
    }
    int main()
    {
    	int n,m,d,q,u,v,w,r,s,ans=0x7f7f7f7f,i,j,k;
    	cin>>n>>m>>d;
    	for(i=1;i<=m;i++)
    	{
    		cin>>u>>v>>w;
    		add(u,v,w);
    		add(v,u,w);
    	}
    	cin>>q;
    	for(i=1;i<=d+1;i++)
    	{
    		dijkstra(i);
    	}
    	if(d==0)
    	{
    		cout<<dis[1][n]<<endl;  
    	}
    	else
    	{
    		memset(f,0x3f,sizeof(f));
    		for(i=1;i<=q;i++)
    		{
    			cin>>r>>s;
    			viss[s]|=1<<(r-2);
    		}
    		for(i=1;i<=d+1;i++)
    		{
    			if(viss[i]==0)
    			{
    				f[0][i]=dis[1][i];
    			}
    		}
    		for(i=0;i<=(1<<d)-1;i++)
    		{
    			for(j=2;j<=d+1;j++)
    			{
    				if((i>>(j-2))&1)
    				{
    					for(k=2;k<=d+1;k++)
    					{
    						if(((i>>(k-2))&1)==0&&(i&viss[k])==viss[k])
    						{
    							f[del(i,k-2)][k]=min(f[del(i,k-2)][k],f[del(i,j-2)][j]+dis[j][k]);
    						}
    					}
    				}
    			}
    		}
    		for(i=2;i<=d+1;i++)
    		{
    			ans=min(ans,f[del((1<<d)-1,i-2)][i]+dis[i][n]);
    		}
    		cout<<ans<<endl;
    	}
    	return 0;
    }
    

3.5

闲话

  • 下午到机房后发现 @K8He@jijidawang 也来 \(1\) 机房了。
  • \(miaomiao\)\(3\) 机房收拾了一下,不知道干啥用的。
  • 晚上因中考报名需要,让我们去刷脸和身份证。给我刷的是我原班主任,她让我刷完还把身份证放在她那里,说这学期经常要用。

做题纪要

luogu P3879 [TJOI2010] 阅读理解

  • \(Trie\) 树板子。

  • 需要 bitset 优化。

    点击查看代码
    int trie[5000010][30],tot=0;
    bitset<1010>vis[5000010];
    char s[5010];
    int val(char x)
    {
    	return x-'a'+1;
    }
    void insert(char s[],int len,int id)
    {
    	int x=0,i;
    	for(i=1;i<=len;i++)
    	{
    		if(trie[x][val(s[i])]==0)
    		{
    			tot++;
    			trie[x][val(s[i])]=tot;
    		}
    		x=trie[x][val(s[i])];
    	}
    	vis[x][id]=1;
    }
    void find(char s[],int len,int n)
    {
    	int x=0,flag=0,i;
    	for(i=1;i<=len;i++)
    	{
    		if(trie[x][val(s[i])]==0)
    		{
    			flag=1;
    			break;
    		}
    		x=trie[x][val(s[i])];
    	}
    	if(flag==0)
    	{
    		for(i=1;i<=n;i++)
    		{
    			if(vis[x][i]==1)
    			{
    				cout<<i<<" ";
    			}
    		}
    	}
    	cout<<endl;
    }
    int main()
    {
    	int n,m,l,i,j;
    	cin>>n;
    	for(i=1;i<=n;i++)
    	{
    		cin>>l;
    		for(j=1;j<=l;j++)
    		{
    			cin>>(s+1);
    			insert(s,strlen(s+1),i);
    		}
    	}
    	cin>>m;
    	for(i=1;i<=m;i++)
    	{
    		cin>>(s+1);
    		find(s,strlen(s+1),n);
    	}
    	return 0;
    }
    

luogu P2831 [NOIP2016 提高组] 愤怒的小鸟

  • 先处理求过两点的的二次函数问题。

    • 设两点分别为 \((x_{1},y_{1})\)\((x_{2},y_{2})\) ,则有 \(\begin{cases}ax_{1}^{2}+bx_{1}+c=y_{1} \\ ax_{2}^{2}+bx_{2}+c=y_{2} \\ c=0 \end{cases}\) ,解得 \(\begin{cases}a=\frac{x_{2}y_{1}-x_{1}y_{2}}{x_{1}^{2}x_{2}-x_{1}x_{2}^{2}} \\ b=\frac{x_{2}^{2}y_{1}-x_{1}^{2}y_{2}}{x_{1}x_{2}^{2}-x_{1}^{2}x_{2}} \\ c=0 \end{cases}\)
  • \(f_{i}\) 表示“消灭小猪状态”对应的二进制数为 \(i\) 时需要的最少抛物线数。

  • 因学校评测机比 luogu 和 LibreOJ 的评测机慢太多了,所以略带卡常。

    点击查看代码
    const double eps=1e-12;
    int f[(1<<20)+10];
    double x[20],y[20];
    int main()
    {   
    	register int t,n,m,s,i,j,k,h,v;
    	double a,b;
    	scanf("%d",&t);
    	for(v=1;v<=t;++v)
    	{
    		scanf("%d%d",&n,&m);
    		for(i=0;i<n;++i)
    		{
    			scanf("%lf%lf",&x[i],&y[i]);
    		}
    		for(i=0;i<(1<<n);++i)
    		{
    			f[i]=__builtin_popcount(i);
    		}
    		for(i=0;i<(1<<n);++i)
    		{
    			for(j=0;j<n;++j)
    			{
    				if((i>>j)&1)
    				{
    					for(k=j+1;k<n;++k)
    					{
    						if(((i>>k)&1)&&fabs(x[j]-x[k])>eps)
    						{
    							a=(x[k]*y[j]-x[j]*y[k])/(x[j]*x[j]*x[k]-x[j]*x[k]*x[k]);
    							if(0-a>eps)
    							{
    								b=(x[k]*x[k]*y[j]-x[j]*x[j]*y[k])/(x[j]*x[k]*x[k]-x[j]*x[j]*x[k]);
    								s=0;
    								for(h=0;h<n;++h)
    								{
    									if(fabs(a*x[h]*x[h]+b*x[h]-y[h])<eps)
    									{
    										s+=(1<<h);
    									}
    								}
    								if(i>=s)
    								{
    									f[i]=min(f[i],f[i-s]+1);
    								}
    							}
    						}
    					}
    				}
    			}
    		}
    		printf("%d\n",f[(1<<n)-1]);
    	}
    	return 0;
    }
    

3.6

闲话

  • 看了眼学号,我 \(52\) 号( \(60\) 个人)。
  • 下午到机房的时候发现 \(1\) 机房开全网了,然后 \(16:40\) 左右又关了。
  • \(miaomiao\) 解释了些直升政策,描述了下 HZ 的宿舍简陋情况(包括但不限于宿舍没有立柜和床下柜子,厕所和淋浴间,基本没有空铺),解释了不让我们去 HZ 的原因(高一的强者都在 HZ );让我们自己说选择去哪个校区;等假期的时候再给我们安排上高一的 whk 不至于开了学后的 whk 学习太被动;还让给家长说周六下午放假的时候来学校开个短会,准备签合同的事情。
  • \(miaomiao\) 说 S2 和 ZZ 那边这届初三实力不是很强,说我们应该是 HE 初三最强的一批人了。
    • 事情真相与否仍持怀疑态度。
  • \(miaomiao\) 说明天下午他给我们安排一场 \(4h\) 的模拟赛,但明天第 \(1,6,7,8\) 节课是奥赛正课,第 \(9\) 节课是奥赛自习,第 \(10\) 节课是公自。 \(miaomiao\) 说下午回去上半个多小时公自没啥用,就直接待到吃饭就行;第 \(1\) 节课直接来这里就行了。

做题纪要

luogu P3622 [APIO2007]动物园

  • \(f_{i,j}\) 表示到第 \(i\) 只动物时“第 \(i+4,i+3,i+2,i+1,i\) 只动物存在状态”对应的二进制数为 \(j\) 时前 \(i\) 个小朋友中最多能让多少个小朋友高兴。状态转移方程为 \(f_{i,j}=\max(f_{i-1,(j-((j \ll 4) \gg 4)) \ll 1},f_{i-1,((j-((j \ll 4) \gg 4)) \ll 1)+1})+g_{i,j}\) 。其中 \(g_{i,j}\) 表示“第 \(i+4,i+3,i+2,i+1,i\) 只动物存在状态”对应的二进制数为 \(j\) 时能让多少个小朋友高兴。

    • 特别地,如果编号超过 \(n\) 将继续从 \(1\) 开始算。
    点击查看代码
    int f[60000][40],g[60000][40];
    int main()
    {
    	int n,m,e,ff,l,x,y,fear,like,ans=0,i,j,k;
    	cin>>n>>m;
    	for(i=1;i<=m;i++)
    	{
    		cin>>e>>ff>>l;
    		fear=like=0;
    		for(j=1;j<=ff;j++)
    		{
    			cin>>x;
    			fear+=(1<<((x-e+n)%n));
    		}
    		for(j=1;j<=l;j++)
    		{
    			cin>>y;
    			like+=(1<<((y-e+n)%n));
    		}
    		for(j=0;j<=(1<<5)-1;j++)
    		{
    			g[e][j]+=((fear&(~j))||(like&j));
    		}
    	}  
    	for(i=0;i<=(1<<5)-1;i++)
    	{
    		memset(f[1],-0x3f,sizeof(f[1]));
    		for(k=0;k<=(1<<5)-1;k++)
    		{
    			if(((k-((k>>4)<<4))<<1)==i||(((k-((k>>4)<<4))<<1)+1)==i)
    			{
    				f[1][k]=g[1][k];
    			}
    		}
    		for(j=2;j<=n;j++)
    		{
    			for(k=0;k<=(1<<5)-1;k++)
    			{
    				f[j][k]=max(f[j-1][(k-((k>>4)<<4))<<1],f[j-1][((k-((k>>4)<<4))<<1)+1])+g[j][k];
    			}
    		}
    		ans=max(ans,f[n][i]);
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    

3.7

闲话

  • \(miaomiao\) 下午 \(14:00 \sim 18:05\) 安排了一场模拟赛。
  • 班里又成了 \(55\) 个人。

做题纪要

luogu P4163 [SCOI2007]排列

  • 多倍经验: CF401D Roman and Numbers
  • \(f_{i,j}\) 表示“当前的排列的数在数字串中是否已经选择”所对应的二进制数为 \(i\) 时,且模 \(d\) 后等于 \(j\) 的方案数。状态转移方程为 \(f_{i+(1 \ll j),(10k+val(s_{j})) \bmod d}=\sum\limits_{k=0}^{d-1}f_{i,k}\)
  • 由于是多重集全排列,最终要注意去重。
    • 第一种方法是设 \(g_{i}\) 表示 \(i\) 在数字串出现的个数看,最终有 \(\frac{f_{(1 \ll |s|)-1,0}}{\prod\limits_{i=0}^{9}g_{i}}\) 即为所求。

      点击查看代码
      int g[12],f[(1<<12)+10][1010];
      char s[12];
      int val(char x)
      {
      	return x-'0';
      }
      int main()
      {
      	int t,n,d,i,j,k,h;
      	cin>>t;
      	for(h=1;h<=t;h++)
      	{
      		memset(g,0,sizeof(g));
      		memset(f,0,sizeof(f));
      		f[0][0]=1;
      		cin>>s>>d;
      		n=strlen(s);
      		for(i=0;i<=n-1;i++)
      		{
      			g[val(s[i])]++;
      		}
      		for(i=0;i<=(1<<n)-1;i++)
      		{
      			for(j=0;j<=n-1;j++)
      			{
      				if(((i>>j)&1)==0)
      				{
      					for(k=0;k<=d-1;k++)
      					{       
      						f[i+(1<<j)][(k*10%d+val(s[j])%d)%d]+=f[i][k];
      					}
      				}
      			}
      		}
      		for(i=0;i<=9;i++)
      		{   
      			for(j=1;j<=g[i];j++)
      			{
      				f[(1<<n)-1][0]/=j;
      			}
      		}
      		cout<<f[(1<<n)-1][0]<<endl;
      	}
      	return 0;
      }
      
    • 第二种方法是在转移的过程中,判断进行转移的这一位是否以前已经处理过了。

      点击查看代码
      int vis[12],f[(1<<12)+10][1010];
      char s[12];
      int val(char x)
      {
      	return x-'0';
      }
      int main()
      {
      	int t,n,d,i,j,k,h;
      	cin>>t;
      	for(h=1;h<=t;h++)
      	{
      		memset(f,0,sizeof(f));
      		f[0][0]=1;
      		cin>>s>>d;
      		n=strlen(s);
      		for(i=0;i<=(1<<n)-1;i++)
      		{
      			memset(vis,0,sizeof(vis));
      			for(j=0;j<=n-1;j++)
      			{
      				if(((i>>j)&1)==0&&vis[val(s[j])]==0)
      				{
      					vis[val(s[j])]=1;
      					for(k=0;k<=d-1;k++)
      					{       
      						f[i+(1<<j)][(k*10%d+val(s[j])%d)%d]+=f[i][k];
      					}
      				}
      			}
      		}
      		cout<<f[(1<<n)-1][0]<<endl;
      	}
      	return 0;
      }
      

luogu P2167 [SDOI2009]Bill的挑战

  • \(f_{i,j}\) 表示截止到每个字符串的第 \(i\) 位时“字符串匹配状态”对应的二进制数为 \(j\) 时的方案数。状态转移方程为 \(f_{i,j \And g_{i,k}}+=f_{i-1,j}\) 。其中 \(g_{i,k}\) 表示“选取的 \(T\) 的第 \(i\) 位是 \(k\) 时所能匹配的字符串状态”对应的二进制数。

    点击查看代码
    const ll p=1000003;
    ll f[60][(1<<16)+10],g[60][30];
    char s[16][60];
    int val(char x)
    {
    	return x-'a'+1;
    }
    int main()
    {
    	ll t,n,m,len,ans,i,j,k,h;
    	cin>>t;
    	for(h=1;h<=t;h++)
    	{
    		cin>>n>>m;
    		ans=0;
    		memset(f,0,sizeof(f));
    		memset(g,0,sizeof(g));
    		for(i=0;i<=n-1;i++)
    		{
    			cin>>(s[i]+1);
    		}
    		len=strlen(s[0]+1);
    		for(i=0;i<=n-1;i++)
    		{
    			for(j=1;j<=len;j++)
    			{
    				for(k=1;k<=26;k++)
    				{
    					if(s[i][j]=='?'||val(s[i][j])==k)
    					{
    						g[j][k]|=(1<<i);
    					}
    				}
    			}
    		}
    		f[0][(1<<n)-1]=1;
    		for(i=1;i<=len;i++)
    		{
    			for(j=0;j<=(1<<n)-1;j++)
    			{
    				if(f[i-1][j]!=0)
    				{
    					for(k=1;k<=26;k++)
    					{
    						f[i][j&g[i][k]]=(f[i][j&g[i][k]]+f[i-1][j])%p;
    					}
    				}
    			}
    		}
    		for(i=0;i<=(1<<n)-1;i++)
    		{
    			if(__builtin_popcount(i)==m)
    			{
    				ans=(ans+f[len][i])%p;
    			}
    		}
    		cout<<ans<<endl;
    	}
    	return 0;
    }
    

luogu P5119 [USACO18DEC]Convention

  • 简单的二分答案。

    点击查看代码
    int t[200000];
    bool check(int mid,int n,int m,int c)
    {
    	int sum=0,last=0,i;
    	for(i=1;i<=n;i++)
    	{
    		if(last==0||i-last>=c||t[i]-t[last]>mid)
    		{
    			sum++;
    			last=i;
    		}
    	}
    	return sum>m;
    }
    int main()
    {
    	int n,m,c,l=0,r,mid,i;
    	cin>>n>>m>>c;
    	for(i=1;i<=n;i++)
    	{
    		cin>>t[i];  
    	}
    	sort(t+1,t+1+n);
    	r=t[n]-t[1];
    	while(l<=r)
    	{
    		mid=(l+r)/2;
    		if(check(mid,n,m,c)==true)
    		{
    			l=mid+1;
    		}
    		else
    		{
    			r=mid-1;
    		}
    	}
    	cout<<l<<endl;
    	return 0;
    }
    

3.8

闲话

  • 上午到机房的时候,发现 \(huge\) 和高一的在机房,然后 \(huge\)\(miaomiao\) 说了下,就让我们来 \(3\) 机房了。 \(3\) 机房只是表面收拾了下,电脑内存仅有 \(4GB\) ,跑不了 \(Linux \ 2.0\) ,动不动就死机。
  • 下午去机房的路上,发现高一的放假了。
  • \(miaomiao\) 下午从坏的电脑主机里把内存条拆了安装到好的电脑上,然后电脑内存就变成了 \(8GB\)
  • @Pursuing_OIer\(miaomiao\) 交涉了下,然后第 \(10\) 节课也改成奥赛课了。

做题纪要

CF1110B Tape

  • \(n\) 个点是必须要进行覆盖的,然后贪心地选取 \(n-k\) 段区间即可。

    点击查看代码
    ll a[200000],len[200000];
    int main()
    {
        ll n,m,k,i,ans=0;
        cin>>n>>m>>k;
        for(i=1;i<=n;i++)
        {
            cin>>a[i];
            len[i]=a[i]-a[i-1]-1;
        }
        ans=n;
        sort(len+2,len+1+n);
        for(i=2;i<=n-k+1;i++)
        {
            ans+=len[i];
        }
        cout<<ans<<endl;    
        return 0;
    }   
    

luogu P3226 [HNOI2012]集合选数

  • 构造一个矩阵 \(A\) 使得 \(\begin{cases} A_{1,1} \bmod 2 \ne 0,A_{1,1} \bmod 3 \ne 0 \\ A_{i,1}=3A_{i-1,1} & i>1 \\ A_{1,j}=2A_{1,j-1} & j>1 \\ A_{i,j}=3A_{i-1,j}=2A_{i,j-1} & i>1,j>1 \end{cases}\) ,形如 \(\begin{bmatrix} 1 & 2 & 4 & \dots \\ 3 & 6 & 12 & \dots \\ 9 & 18 & 36 & \dots \\ \dots & \dots & \dots & \dots \end{bmatrix}\) 。由题意,构造的矩阵 \(A\) 中相邻四个方向的元素不能同时选。

  • 构造多个矩阵使得其内部元素恰好包含 \(1 \sim n\) ,然后利用乘法原理求解即可。

    点击查看代码
    const ll p=1000000001;
    ll a[20][20],m[20],f[20][(1<<20)+10],vis[(1<<20)+10];
    int main()
    {
    	ll n,maxn,ans=1,num,flag,sum,i,j,k,h;
    	cin>>n;
    	for(h=1;h<=n;h++)
    	{
    		if(h%2!=0&&h%3!=0)
    		{
    			memset(a,0,sizeof(a));  
    			memset(m,0,sizeof(m));  
    			num=0;
    			a[1][1]=h;
    			maxn=m[1]=1;
    			for(j=2;a[1][j-1]*2<=n;j++)
    			{
    				a[1][j]=a[1][j-1]*2;
    				m[1]=j;
    			}
    			for(i=2;a[i-1][1]*3<=n;i++)
    			{
    				a[i][1]=a[i-1][1]*3;
    				m[i]=1;
    				maxn=i;
    			}
    			for(i=2;i<=maxn;i++)
    			{
    				for(j=2;a[i-1][j]*3<=n;j++)
    				{
    					a[i][j]=a[i-1][j]*3;
    					m[i]=j;
    				}
    			}
    			f[0][0]=1;
    			for(i=0;i<=(1<<m[1])-1;i++)
    			{
    				flag=sum=0;
    				for(j=0;j<=m[1]-1;j++)
    				{   
    					if(((i>>j)&1)==0)
    					{
    						if(sum>=2)
    						{
    							flag=1;
    							break;
    						}
    						sum=0;
    					}
    					else
    					{
    						sum++;
    					}
    				}
    				vis[i]=(flag==0&&sum<=1);
    			}
    			for(i=1;i<=maxn;i++)
    			{
    				for(j=0;j<=(1<<m[i])-1;j++)
    				{
    					f[i][j]=0;
    					if(vis[j]==1)
    					{
    						for(k=0;k<=(1<<m[i-1])-1;k++)
    						{
    							if((j&k)==0&&vis[k]==1)
    							{
    								f[i][j]=(f[i][j]+f[i-1][k])%p;
    							}
    						}
    					}
    				}
    			}
    			for(i=0;i<=(1<<m[maxn])-1;i++)
    			{
    				num=(num+f[maxn][i])%p;
    			}
    			ans=ans*num%p;
    		}
    	}
    	cout<<ans<<endl;
    	return 0;
    } 
    

3.9

闲话

  • 教职工考试貌似占了高一的教室,所以高一的昨天放假了,今天下午返校了。
  • 下午看自己电脑还是 \(4GB\) ,和 \(miaomiao\) 说了后他说等会给我安内存条。我想借这个理由和 \(miaomiao\) 交涉先把自己电脑要回来,但 \(miaomiao\) 把内存条给我安上了,所以和 \(miaomiao\) 的交涉失败了。
  • 下午 \(miaomiao\) 让组织讲题,但我们都不是很愿意去讲,然后 @K8He 就把 @APJifengc 的讲题圣经 【日总结】2022.11.14 推给了我们,间接性地 \(D\) 看我们一下。
  • 下午大课间的时候 \(feifei\) 来喊我们回班准备签合同。去找 \(feifei\) 拿了电脑,此时教练办公室里只有 \(feifei\)\(field\)
  • 回班正赶上奥赛主任给家长讲完话,然后是各科教练单独给家长讲话。和家长软磨硬泡后,让家长同意签合同了。
  • 签完合同已经快 \(16:30\) 了,回宿舍拿了行李就直接出校了。

做题纪要

3.10

闲话

  • 下午 \(15:00 \sim 16:00\) 进校,让 \(16:30\) 到教室坐好。貌似从昨天出教室到今天在教室坐好之间正好一天,还多 \(5min\)
  • 返校前问 \(miaomiao\) 下午有课吗, \(miaomiao\) 说没课,所以我就直接回班了。 \(16:25\) 的时候代班主任查人的时候发现信奥的都没在班里,我就去机房了。
  • 到机房后 \(3\) 机房被小孩哥占了,我们又被发配到了 \(1,2\) 机房。

做题纪要

luogu P2656 采蘑菇

  • 缩点板子。

    点击查看代码
    struct node
    {
    	int nxt,to,w,z;
    }e[500000];
    stack<int>s;
    int head[500000],dfn[500000],low[500000],ins[500000],dis[50000],vis[500000],c[500000],u[500000],v[500000],w[500000],z[500000],b[500000],tot=0,ans=0,cnt=0;
    void add(int u,int v,int w,int z)
    {
    	cnt++;
    	e[cnt].nxt=head[u];
    	e[cnt].to=v;
    	e[cnt].w=w;
    	e[cnt].z=z;
    	head[u]=cnt;
    }
    void tarjan(int x)
    {
    	int i,k=0;
    	tot++;
    	dfn[x]=low[x]=tot;
    	ins[x]=1;
    	s.push(x);
    	for(i=head[x];i!=0;i=e[i].nxt)
    	{
    		if(dfn[e[i].to]==0)
    		{
    			tarjan(e[i].to);
    			low[x]=min(low[x],low[e[i].to]);
    		}
    		else
    		{
    			if(ins[e[i].to]==1)
    			{
    				low[x]=min(low[x],dfn[e[i].to]);
    			}
    		}
    	}
    	if(dfn[x]==low[x])
    	{
    		ans++;
    		while(x!=k)
    		{
    			k=s.top();
    			ins[k]=0;
    			c[k]=ans;
    			s.pop();
    		}
    	}
    }
    void spfa(int s)
    {
    	int i,x;
    	queue<int>q;
    	q.push(s);
    	dis[s]=b[s];
    	vis[s]=1;
    	while(q.empty()==0)
    	{
    		x=q.front();
    		vis[x]=0;
    		q.pop();
    		for(i=head[x];i!=0;i=e[i].nxt)
    		{
    			if(dis[e[i].to]<dis[x]+e[i].w+b[e[i].to])
    			{
    				dis[e[i].to]=dis[x]+e[i].w+b[e[i].to];
    				if(vis[e[i].to]==0)
    				{
    					q.push(e[i].to);
    					vis[e[i].to]=1;
    				}
    			}
    		}
    	}
    }
    int main()
    {
    	int n,m,s,sum=0,i;
    	double zz;
    	cin>>n>>m;
    	for(i=1;i<=m;i++)
    	{
    		cin>>u[i]>>v[i]>>w[i]>>zz;
    		z[i]=zz*10;
    		add(u[i],v[i],w[i],z[i]);
    	}
    	cin>>s;
    	for(i=1;i<=n;i++)
    	{
    		if(dfn[i]==0)
    		{
    			tarjan(i);
    		}
    	}
    	cnt=0;
    	memset(e,0,sizeof(e));
    	memset(head,0,sizeof(head));
    	for(i=1;i<=m;i++)
    	{
    		if(c[u[i]]!=c[v[i]])
    		{
    			add(c[u[i]],c[v[i]],w[i],z[i]);
    		}
    		else
    		{
    			while(w[i]!=0)
    			{
    				b[c[u[i]]]+=w[i];
    				w[i]=w[i]*z[i]/10;
    			}
    		}
    	}
    	spfa(c[s]);
    	for(i=1;i<=n;i++)
    	{
    		sum=max(sum,dis[i]);
    	}
    	cout<<sum<<endl;
    	return 0;
    }
    

tgHZOJ 2891. 回文

tgHZOJ 2892. 快速排序

posted @ 2024-03-04 18:04  hzoi_Shadow  阅读(107)  评论(3编辑  收藏  举报
扩大
缩小