10.24三题

10.24今日三题

CF645E Intellectual Inquiry

给定长度为\(m\)字符串,在字符串后添加\(n\)个字符,使新字符包含不同的子序列数尽量多,求最多的不同子序列数量

转移分两种情况

当前字符未出现

\[f[i]=f[i]*2+1; \]

当前字符出现过

\[f[i]=f[i-1]*2-f[last[s[i]]-1] \]

最后每次贪心选取\(last_i\)最小的字符,使减的最小,\(f_i\)最大

char s[N>>1]; int n,k,len,lst[200];ll f[N];
priority_queue<pair<ll,int> >q;
int main(){
	scanf("%d%d",&n,&k);
	scanf("%s",s + 1); len = strlen(s + 1);
	for(int i = 1;i <= len;++i){
		if(!lst[s[i]]) f[i] = (f[i-1] <<1|1) % mod;
		else f[i] = ((f[i-1]<<1) - f[lst[s[i]]-1] + mod) % mod;
		lst[s[i]] = i;
	}
	for(char i = 'a';i < 'a' + k;++i)
		q.push(make_pair(-lst[i],i));
	for(int i = 1;i <= n;++i){
		int minn = -q.top().first;
		int pos = q.top().second; q.pop();
		int now = i + len;
		if(!minn) f[now] = (f[now-1]<<1|1) % mod;
		else{
			f[now] = ((f[now-1]<<1) - f[minn-1] + mod) % mod;
		}
		lst[pos] = now;
		q.push(make_pair(-now,pos));
	}
	ll ans = f[n + len] + 1;
	printf("%lld",ans);
}
CF859E Desk Disorder

偷的\(HE\)轰态氧\(chpu437\)的图\(2333\)

\(2N\)个节点\(N\)个人,每个人位于节点上,每个人都有想去的节点(可以是当前点),一个人可以保持在当前点不动,也可以去想去的点,为保证不存在一个点上有超过一个人的方案数有多少种

根据题意,图中至多会存在一个出度为\(0\)的点,分类讨论

\(1.\)有一个这样的点

CF859E_1.png

显然这玩意是个树,除去根,对于树上的节点,如果它要到达下一个节点,它指向节点这一路径所有点前进一步,每个点都有这样一个方案,方案为\(n-1\)种,所有点不动,有一种方案,总共\(n\)种方案

当树上有自环,你会发现只能有一种方案,所以要判一下

\(2.\)不存在这样的点

CF859E_2.png

对于一个环,只有全部移动和全部不动,对于基环树,每个链不可动,所以方案数均为\(2\)

题目有自环,自环显然方案为\(1\)

用各路玄学判环即可:冰茶几,大法师,脱蒲排序(Orz大帝),

最后乘法原理一乘即可

int fa[N],siz[N]; bool deg[N],circle[N],selfcir[N];
int find(int x){return fa[x] == x ? x : fa[x] = find(fa[x]);}
int main(){
	int n;long long ans = 1; n = read();
	for(int i = 1;i <= n<<1;++i){
		fa[i] = i; siz[i] = 1;
	} int u,v;
	for(int i = 1;i <= n;++i){
		u = read(); v = read(); deg[u] = true;
		if(u == v){
			selfcir[u] = true;
			continue;
		}
		else{
			u = find(u); v = find(v);
			if(u == v && !selfcir[u]){
				ans = (ans<<1) > mod ? (ans<<1) - mod : (ans<<1);
				circle[u] = true; continue;
			}
			siz[v] += siz[u]; selfcir[v] |= selfcir[u];//判断树上自环 
			fa[u] = v;
		}
	}
	for(int i = 1;i <= n<<1;++i){
		if(!deg[i] && !selfcir[i])//如果树上有自环,相当于乘1 
			ans = (ans * siz[i]) % mod;
	}
	printf("%lld",ans);
}
P6822 [PA2012]Tax

给出一个\(n\)个点,\(m\)条边的无向图,经过一个点代价是进入和离开这个点的两条边的边权较大值,求\(1\)\(n\)的最小代价,起点的代价是离开起点的边的边权,终点的代价是进入终点边的边权

权值收到两条边影响,考虑给边建边,在新图跑最短路

naive想法是\(a\to b\to c\)边设成\(\max(z1,z2)\),跑最短路,但是边数是\(m^2\)

建立超级源点\(s\)和超级汇点\(t\),无向边拆成有向边,边转点,

对于所有从\(1\)出发的边,从\(s\)向这些边对应的点连权值为原图权值的边

枚举\(b\)点,把\(b\)的所有出边编号找出,然后按边权排序,把边编号直接做差相连,边数会变成\(m\)

跑最短路即可

# define pli std::pair<long long, int>
# define mkp std::make_pair
struct edge {
	int v, next; long long w; int id;
	const bool operator < (const edge that) const {
		return this->w < that.w;
	}
} e[MAXM<<1];
int hd[MAXM<<1], cntE;
long long dis[MAXM<<1];
bool vis[MAXM<<1];
std::vector<edge>vec[MAXN];
void AddE(int u, int v, long long w) {
	e[++cntE] = (edge) {v, hd[u], w, 0};
	hd[u] = cntE;
}
void Dij(int s, int t) {
	memset(dis, 0x3f, sizeof(dis));
	std::priority_queue<pli, std::vector<pli>, std::greater<pli> >H;
	dis[s] = 0;
	H.push(mkp(dis[s], s));
	while(H.size()) {
		int now = H.top().second;
		H.pop();
		if(!vis[now]) {
			vis[now] = true;
			for(int i = hd[now]; i; i = e[i].next) {
				if(dis[e[i].v] > dis[now] + e[i].w) {
					dis[e[i].v] = dis[now] + e[i].w;
					H.push(mkp(dis[e[i].v], e[i].v));
				}
			}
		}
	}
}
int main() {
	int n, m; scanf("%d%d", &n, &m); int s = 0, t = 1;
	for(int i = 1, u, v, w; i <= m; i++) {
		scanf("%d%d%d", &u, &v, &w);
		vec[u].push_back((edge){v, 0, w, i<<1});
		vec[v].push_back((edge){u, 0, w, i<<1|1});
	}
	for(int i = 1; i <= n; i++) {
		if(vec[i].size()) {
			std::sort(vec[i].begin(), vec[i].end());
			for(int j = 0; j < vec[i].size(); j++) {
				AddE(vec[i][j].id^1, vec[i][j].id, vec[i][j].w);
				if(i == 1)
					AddE(s, vec[i][j].id, vec[i][j].w);
				if(vec[i][j].v == n)
					AddE(vec[i][j].id, t, vec[i][j].w);
			}
			for(int j = 1; j < vec[i].size(); j++){
				AddE(vec[i][j].id, vec[i][j-1].id, 0);
				AddE(vec[i][j-1].id, vec[i][j].id, vec[i][j].w-vec[i][j-1].w);
			}
		}
	}
	Dij(s, t);
	printf("%lld", dis[t]);
	return 0;
}
posted @ 2020-10-24 12:06  INFP  阅读(81)  评论(0编辑  收藏  举报