首页 > 其他分享 >【luogu AGC035E】Develop(分类讨论)(DP)

【luogu AGC035E】Develop(分类讨论)(DP)

时间:2022-10-24 18:37:30浏览次数:80  
标签:Develop int luogu ll 然后 ++ AGC035E DP

Develop

题目链接:luogu AGC035E

题目大意

一开始有 -1e18~1e18 的所有整数,然后你每次操作可以在 1~N 中选一个还在的数 x,擦掉他,然后查看 x-2,x+K,如果没有就把数加上。
然后问你你操作若干次之后,剩下的数有多少中情况。

思路

考虑先把有跟没有互换。
然后发现如果我们要 \(x,x-2\) 同时都出现,那我们一定要先弄 \(x\),再弄 \(x-2\),不然会把 \(x-2\) 擦掉。

然后对于这个关系我们建一条边 \(x\rightarrow x-2\),同理有 \(x\rightarrow x+k\)。
那也就是说我们要选一些点集,使得不存在环。
(因为只有是 DAG 你才能安排出顺序)

然后我们按 \(k\) 的奇偶性进行讨论。
如果 \(k\) 是偶数,那形成的环就是 \(x,x+2,...,x+k,x\) 这样的。
那就是我们把位置奇偶分别做一次,就不能出现连续的 \(k/2\) 个都选你的情况,直接 \(f_{i,j}\) 前 \(i\) 个位置,最后选了连续的 \(j\) 个的情况,直接 DP 即可。

如果 \(k\) 是奇数,那考虑环是什么样的。
会发现可以形如在偶数的下标跳若干个 \(2\),然后跳一下 \(k\),在奇数的部分跳一段 \(2\),再跳 \(k\)。

盗用一张图就是这样的:)
在这里插入图片描述

然后你把 \(x,x+k\) 分在同一层,那我们可以理解为一个环是这样的一条路径:
往上,往右,往上。
然后两次往上的和 \(k+1\),也就是总共的长度是 \(k+1\)。
那你也可以 DP,设 \(f_{i,j,k}\) 为前 \(i\) 层当前的路径长度是 \(j\),右边一条值的路径的长度是 \(k\)。

然后转移一下即可。

代码

#include<cstdio>
#include<iostream>
#define ll long long

using namespace std;

const int N = 155; 
int n, K;
ll mo, f[N][N], g[N << 1][N][N];

void slove1() {
	f[0][0] = 1;
	for (int i = 0; i < n; i++)
		for (int j = 0; j <= K / 2; j++) {
			if (!f[i][j]) continue;
			if (j + 1 <= K / 2) (f[i + 1][j + 1] += f[i][j]) %= mo;
			(f[i + 1][0] += f[i][j]) %= mo;
		}
	ll ans1 = 0, ans2 = 0;
	for (int i = 0; i <= K / 2; i++) (ans1 += f[n / 2][i]) %= mo, (ans2 += f[(n + 1) / 2][i]) %= mo;
	printf("%lld", ans1 * ans2 % mo);
}

//i - i+K
void slove2() {
	g[0][0][0] = 1; int nxt = 0;
	for (int i = 0; i < n + K - 1; i += 2) { nxt = i + 2;
		for (int j = 0; j <= K + 1; j++)
			for (int k = 0; k <= n; k++)
				(g[i + 2][0][0] += g[i][j][k]) %= mo;
		if (i + 2 <= n) {
			for (int j = 0; j <= K + 1; j++)
				for (int k = 0; k <= n; k++)
					(g[i + 2][0][k + 1] += g[i][j][k]) %= mo;
		}
		if (i + 2 >= 1 + K) {
			for (int j = 1; j < K + 1; j++)
				for (int k = 0; k <= n; k++)
					(g[i + 2][j + 1][0] += g[i][j][k]) %= mo;
			for (int k = 0; k <= n; k++)
				(g[i + 2][0][0] += g[i][0][k]) %= mo;//1 0
		}
		if (i + 2 <= n && i + 2 >= 1 + K) {
			for (int j = 0; j < K + 1; j++) {
				for (int k = 0; k < n && k < K; k++) {
					(g[i + 2][max(k + 2, j + 1)][k + 1] += g[i][j][k]) %= mo;
				}
			}
		}
	}
	ll ans = 0;
	for (int j = 0; j <= K + 1; j++)
		for (int k = 0; k <= n; k++)
			(ans += g[nxt][j][k]) %= mo;
	printf("%lld", ans);
}

int main() {
	scanf("%d %d %lld", &n, &K, &mo);
	
	if (K & 1) slove2();
		else slove1();
	
	return 0;
}

标签:Develop,int,luogu,ll,然后,++,AGC035E,DP
From: https://www.cnblogs.com/Sakura-TJH/p/luogu_AGC035E.html

相关文章

  • luogu P8275 [USACO22OPEN] 262144 Revisited P
    题面传送门这里有个sb写这道题写了一下午。首先来考虑一段子段上的答案,显然答案有一个区间,设最大值为\(E\),则最小值一定在\([E,E+\logn]\)之间。我们考虑按照最大值分......
  • 行为驱动开发Behaviour Driven Development
    BDD(​​BehaviourDrivenDevelopement​​​)最重要的基础概念是业务化的“Story”,缘于一个很显而易见的原因——“软件开发是要服务于业务需要的”,但实际项目中往往因为各......
  • luogu P8585 球状精灵的传说 题解
    题目大意给定\(n\)个精灵的三维幅度\(\{r_{1,i},r_{2,i},r_{3,i}\}\),任意两个精灵若在三个幅度中有两个相同(这里可以乱序)则可以将剩下的一位相加组合起来。组合过的精......
  • Luogu P8348
    构造题。……这玩意儿怎么构造。不过只用判断Yes/No。考虑找一个方法唯一的表示一对数能表示的拓展出的序列包含的所有“一对数”。容易想到一直减到最小,用最终结果......
  • [luogu6575]Friends
    记$s=p+q$,当存在一个点度数$\ges$时,显然无解记$d_{S,T}=\sum_{x\inS,y\inT}[(x,y)\inE]$,称$S\subseteqV$合法当且仅当$|S|\lep$且$d(S,V\backslashS)\leq$结论:若......
  • Luogu P2656采蘑菇(Tarjan + spfa)
    采蘑菇题目描述小胖和ZYR要去ESQMS森林采蘑菇。ESQMS森林间有\(N\)个小树丛,\(M\)条小径,每条小径都是单向的,连接两个小树丛,上面都有一定数量的蘑菇。小胖和ZYR......
  • 【luogu AGC034F】RNG and XOR(FWT)
    RNGandXOR题目链接:luoguAGC034F题目大意给你一个长度为2^n的数组A。一开始有一个\(0\)数,然后每次你随机给它异或上0~2^n-1中的数,随机到\(i\)的概率跟Ai+1......
  • luogu P1972 SDOI2009 HH的项链
    P1972SDOI2009HH的项链-洛谷|计算机科学教育新生态(luogu.com.cn)维护一个长度同为\(n\)的数组\(b\)。一个指针\(R\)从\(1\)扫到\(n\)并做如下操作:检查......
  • 【luogu CF1163F】Indecisive Taxi Fee(图论)(分类讨论)
    IndecisiveTaxiFee题目链接:luoguCF1163F题目大意给你一个无向图,每次改一条边的权值(每次都会变回来),问你1~n的最短路长度。思路考虑分类讨论,先找到最短路的路径,然......
  • 【luogu CF1140F】Extending Set of Points(线段树分治)
    ExtendingSetofPoints题目链接:luoguCF1140F题目大意有一个点集,有一个扩展操作是加入符合条件的(x0,y0)直到不能加入位置。符合条件是原来(x0,y0)不存在而且存......