luogu 记录

luogu 记录

P8215 分组作业

题面:

老师布置了分组作业。在此之前,老师将班上 \(2n\) 个学生分成了 \(n\) 组,每组两个人。其中 \(1\) 号和 \(2\) 号为一组,\(3\) 号和 \(4\) 号为一组,……,\(2n-1\) 号和 \(2n\) 号为一组。

老师让每个队伍自行安排分工。这样是否合作就成了一个大问题。大家决定用表决的方式来确定。首先每个人决定是否愿意和队友合作。不同的人因为自己的原因和分配的队友的原因,对合作的意愿不一样,对于第 \(i\) 个学生,选择“愿意”会产生 \(c_i\) 的不满,选择“不愿意”会产生 \(d_i\) 的不满。

如果两名队友都选择“愿意”,那么根据实际情况他们可以合作或者不合作。但是如果有一名队友选择“不愿意”,那么他们只能不合作。

学生中还有 \(m\) 个单向的喜欢关系,一个关系形如“\(A\) 喜欢 \(B\)”。在这样一个关系中,如果 \(A\) 没有和队友合作,且 \(B\) 选择了“愿意”,\(A\) 会有略微沮丧,产生 \(a_i\) 的不满;如果 \(A\) 表决了“不愿意”,但 \(B\) 成功与队友合作,那么 \(A\) 会羡慕嫉妒恨并产生 \(b_i\) 的不满。(由于当 \(A\)\(B\) 在同一组时这种设定会变得很奇怪,所以题目保证不会有这种情况)其中 \(i\) 表示第 \(i\) 个关系。

如果一个学生 \(i\) 选择了“愿意”但是他的队友选择了“不愿意”,那么他会因为队友产生 \(e_i\) 的不满。

问所有情况下最小的不满之和是多少。

\(1\le n \le 5000\)\(0\le m \le 10000\)\(1\le a_i,b_i,c_i,d_i,e_i\le 10^9\)

题解:

智慧的网络流建图题。

套路的,每个学生都是一个点 \(i\),他有两种选择,都需要付出相应的代价,转化为最小割问题,割到 \(S\) 点集或是 \(T\) 点集分别对应两种选择。即建立边 \((S,i,d_i)\)\((i,T,c_i)\) 我们分别称之为 \(d\) 类边和 \(c\) 类边。

之后再建立对每一组同学 \((i,i+1)\) 建边 \((i,i+1,e_i)\)\((i+1,i,e_{i+1})\)(称之为 \(e\) 类边),表示如果两个人选择状态不一样就会有经过对应 \(e\) 边的 \(S\) 可达 \(T\) 的路径,那就还需要割掉某个 \(e\) 边。

最高妙的地方就是如何处理“喜欢”的限制。

对每组建立点 \(x_i\) 对应组 \((2i-1,2i)\)。若割断后 \(S\) 能到达 \(x_i\) 表示 \(i\) 组选择合作,否则表示不合作。然后建边 \((x_i,2i-1,inf),(x_i,2i,inf)\) (称之为 \(i\) 类边)。

对于每个关系 \(A\) “喜欢” \(B\),建边 \((B,x_{\lceil A/2\rceil},a_i),(x_{\lceil B/2\rceil},A,b_i)\) 称之为 \(a\) 类边和 \(b\) 类边。

正确性可以分类讨论证明。

首先对于 \(a\)\((i,x_j,a_k)\),如果 \(x_j\) 里的组员 \(y\) 选择了不愿意,而 \(i\) 选择了愿意,那么就会有路径 \(S\to i\to x_j\to y\to T\),所以 \(a_k\) 是一定会被割掉的。(不可能不割掉 \(a_k\),如果 \(a_k\) 不割那么由于 \(i\) 边的存在 \(c_{2j-1}\)\(c_{2j}\) 都会割掉,那么 \(y\) 选择不愿意时的 \(d_y\) 就不用割了。)

若一个组 \(x_i\) 只有 \(b\) 边,那么不管组员怎么选都肯定不合作,答案不会变劣,对应到图上即 \(x_i\) 没有入边,所以 \(S\) 也必然不能到达 \(x_i\)

若一个组 \(x_i\) 只有 \(a\) 边,上述论证了如果有人不愿意那 \(a_k\) 肯定会割掉,如果都愿意那选择合作答案肯定不会变劣,这对应了如果两条 \(c\) 边全部割掉那一定没有 \(S\)\(x_i\) 可达 \(T\) 的路径,所以 \(a\) 边也不用割了。

若一个组 \(x_i\) 同时有 \(a,b\) 两种边,那么他割掉的边中肯定不会同时有 \(a,b\) 两种边,这肯定不如把所有 \(a\) 边全割掉或把所有 \(b\) 边全割掉更优。此时若他割掉所有 \(a\) 边表示 \(x_i\) 组不合作,反之表示合作。这两种情况正好分别对应了题目中“喜欢”的两种惩罚状态。

代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;

inline int read(){
	int s=0,k=1;
	char c=getchar();
	while(c>'9'||c<'0'){
		if(c=='-') k=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		s=(s<<3)+(s<<1)+(c^48);
		c=getchar();
	}
	return s*k;
}

const int N=5005,M=10005,inf=1e9+7;
int n,m,S,T,pos[N*2],dep[N*3],E[N*3],head[N*3],cnt=1;
struct edge{
	int v,nxt,w;
}e[N*8+M*2<<1];

void add(int u,int v,int w){
	e[++cnt]={v,head[u],w};
	head[u]=cnt;
	e[++cnt]={u,head[v],0};
	head[v]=cnt;
}

bool bfs(){
	for(int i=S;i<=T;i++) dep[i]=0,E[i]=head[i];
	queue<int>q; q.push(S); dep[S]=1;
	while(!q.empty()){
		int x=q.front(); q.pop();
		for(int i=head[x],v;i;i=e[i].nxt){
			v=e[i].v;
			if(e[i].w&&!dep[v]){
				dep[v]=dep[x]+1;
				q.push(v);
			}
		}
	}
	return dep[T]!=0;
}

int dfs(int x,int W){
	if(x==T) return W;
	int now=0;
	for(int i=E[x],v;i&&now<W;i=e[i].nxt){
		E[x]=i; v=e[i].v;
		if(e[i].w&&dep[v]==dep[x]+1){
			int tmp=dfs(v,min(e[i].w,W-now));
			if(!tmp) dep[v]=-1;
			else{
				now+=tmp;
				e[i].w-=tmp;
				e[i^1].w+=tmp;
				if(now==W) return W;
			}
		}
	}
	return now;
}

ll dinic(){
	ll ans=0;
	while(bfs()) ans+=dfs(S,inf);
	return ans;
}

int main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	n=read();m=read();
	S=0;T=n*3+1;
	for(int i=2;i<=n<<1;i+=2) pos[i-1]=pos[i]=n*2+i/2;
	for(int i=1;i<=n<<1;i++){
		add(pos[i],i,inf);
		int	A=read(),B=read(),C=read();
		add(S,i,B); add(i,T,A);
		add(i,(i-1^1)+1,C);
	}
	for(int i=1;i<=m;i++){
		int u=read(),v=read(),A=read(),B=read();
		int x=pos[u],y=pos[v];
		add(y,u,B); add(v,x,A);
	}
	printf("%lld",dinic());
	return 0;
}

P4548 歌唱王国

题面:

在歌唱王国,所有人的名字都是一个非空的仅包含整数 \(1\sim n\) 的字符串。

王国里生活着一大群咕噜兵,他们靠不停地歌唱首领——牛人酋长们的名字来获取力量。咕噜兵每一次歌唱过程是这样的:首先,他从整数生成器那儿获得一个数字,然后花一个时间单位将此数字唱出来,如果他发现某个牛人酋长的名字已经被歌唱出来(即此名字是歌唱序列的一个连续子串),那么这次歌唱过程就立即结束。

相关名词定义:

  • 歌唱序列:如果某人歌唱了 \(x\) 个数字,第 \(i\) 次歌唱的数字为 \(a_i\),那么歌唱序列 \(=(a_1,a_2,\cdots,a_x)\)
  • 整数生成器:歌唱王国的神物,它有一个按钮,如果你按一下按钮,将从 \(1\sim n\) 数字中等概率的随机返回一个整数。
  • 歌唱时间:在一次歌唱过程中花费的时间。

歌唱时间是随机的,无法预料;不过歌唱时间的期望值是固定的,此期望值即平均来说歌唱时间有多长,亦可称作平均歌唱时间。

王国里的人非常喜欢歌唱,他们希望歌唱的时间越长越好,所以他们决定罢免一些牛人酋长,使得平均歌唱时间变长。但是他们不能罢免掉所有的牛人酋长,否则他们每次歌唱都无法停止,无法获取力量;于是他们决定只保留一个牛人酋长而罢免其余的牛人酋长。

你的任务是:对于给定的 \(n\)、牛人酋长的个数 \(t\) 以及每一个牛人酋长的名字,告诉王国里的人们,对于 \(1\leq i\leq t\),如果保留第 \(i\) 个牛人酋长,罢免掉其余的,那么平均歌唱时间将是多少。

提示:此数为一个非负整数!

输出要求:由于这个数字太大,所以你只需输出这个数的末 \(4\) 位数字。如果不足 \(4\) 位,则前面补 \(0\)\(1\leq n\leq 10^5\)\(t\leq 50\)\(1\leq m_i\leq 10^5\)

题解:

题目即要求对于每个模式串求在文本串中第一次出现的期望长度。

考虑 \(kmp\) 的匹配过程,设当前模式串 \(s\) 长度为 \(k\)\(f(i)\) 表示文本串当前匹配到了模式串的第 \(i\) 个字符之后直到结束还需要的期望步数。初始 \(f(k)=0\)

有转移方程 \(f(i)=1+\frac 1 n\sum_{c=1}^nf(tr(i,c))\)\(tr(i,c)\) 表示前 \(i\) 个字符已经匹配上之后在加入一个字符 \(c\) 会匹配到模式串的哪个位置。即若 \(c=s_{i+1}\),那么 \(tr(i,c)=i+1\),否则 \(tr(i,c)=tr(nxt_i,c)\)

注意到 \(tr(i,c)\)\(tr(nxt_i,c)\) 的结果只有当 \(c=s_{i+1}\) 时不同,所以设 \(j=nxt_i\)\(f(j)-\frac 1 nf(tr(j,s_{i+1}))=f(i)-\frac 1 nf(tr(i,s_{i+1}))\)

因为 \(tr(i,s_{i+1})=i+1,tr(nxt_i,s_{i+1})=nxt_{i+1}\) 化简得 \(f(nxt_i)-f(i)=\frac 1 n(f(nxt_{i+1})-f(i+1))\)

\(g(i)=f(nxt_i)-f(i)\),有转移 \(g(i)=\frac{g(i+1)} n\),边界是 \(g(1)=f(0)-f(1)\)。根据 \(f\) 的转移方程有 \(f(0)=1+\frac{n-1} n f(0)+\frac 1 n f(1)\),即 \(f(0)-f(1)=n\),所以 \(g(1)=n\)\(g(i)=n^i\)

因为 \(f(k)=0\),所以 \(g(k)=f(nxt_k)=n^k\),同理 \(f(nxt_{nxt_k})=n^k+n^{nxt_k}\)。所以答案是从 \(k\) 开始跳 \(nxt\)\(n\) 的沿途位置次幂加和。

代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;

inline ll read(){
	ll s=0,k=1;
	char c=getchar();
	while(c>'9'||c<'0'){
		if(c=='-') k=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		s=(s<<3)+(s<<1)+(c^48);
		c=getchar();
	}
	return s*k;
}

const int N=1e5+5,mod=10000;
int a[N],nxt[N];
ll fac[N];

void Add(ll &x,ll y){
	x+=y;
	if(x>=mod) x-=mod;
}

int main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	fac[0]=1; fac[1]=read();
	for(int i=2;i<N;i++) fac[i]=fac[i-1]*fac[1]%mod;
	int T=read();
	while(T--){
		int n=read();
		for(int i=1;i<=n;i++) a[i]=read();
		nxt[1]=0;
		for(int i=2,j=0;i<=n;i++){
			while(j&&a[i]!=a[j+1]) j=nxt[j];
			if(a[i]==a[j+1]) j++;
			nxt[i]=j;
		}
		ll ans=0;
		for(int i=n;i>=1;i=nxt[i]) Add(ans,fac[i]);
		printf("%04lld\n",ans);
	}
	return 0;
}
posted @ 2025-07-04 15:33  programmingysx  阅读(22)  评论(0)    收藏  举报
Title