CodeForces Round#229 DIV2 C 递推DP

对这道题目也只好说呵呵了,没注意k的范围最大才10,所以昨晚纠结了很久,没什么好的方法来处理,后来无奈想去翻翻题解,发现人家开头就来了句,因为k的范围比较小 所以.........我只好暂停马上回头看看题目,是的,k比较小所以完全可以先在询问前预处理DP一遍,

DP就比较清晰了,dp[i][j]  (i>=0 && i<k,,,,j>=i && j <=n)代表意义呢 以i为开头的  区间[1,j]注意 是 1~j的 所需要的操作数,题目问的是最小操作数,其实我们知道如果要操作那么操作数都是固定的,所以 没什么所谓的最优解了,这样 状态转移可以说完全没有吧,因为就是先接替上一个的值,然后判断当前所在的位置 是否有糖,而且是否是k的倍数来决定是否要进行操作,这样就可以了

int n,k,w;

char s[100000 + 5];

bool vis[100000 + 5];

int dp[12][100000 + 5];

void init() {
	memset(vis,false,sizeof(vis));
	memset(dp,0,sizeof(dp));
}

bool input() {
	while(scanf("%d %d %d",&n,&k,&w) == 3) {
		scanf("%s",s + 1);
		return false;
	}
	return true;
}

void cal() {
	for(int i=1;i<=n;i++)if(s[i] == '1')vis[i] = 1;
	for(int i = 0;i<k;i++) {
		for(int j=i;j<=n;j++) {
			if((j - i + 1)%k == 0 && !vis[j])dp[i][j]++;
			if((j - i + 1)%k != 0 && vis[j])dp[i][j]++;
			dp[i][j] += dp[i][j - 1];
		}
	}
}

void output() {
	while(w--) {
		int x,y;
		scanf("%d %d",&x,&y);
		int tmp = x%k;
		cout<<dp[tmp][y] - dp[tmp][x - 1]<<endl;
	}
}

int main () {
	while(true) {
		init();
		if(input())return 0;
		cal();
		output();
	}
}

CodeForces Round#229 DIV2 C 递推DP

时间: 2025-01-02 06:15:35

CodeForces Round#229 DIV2 C 递推DP的相关文章

Codeforces Round #260(div2)C(递推)

有明显的递推关系: f[i]表示i为数列中最大值时所求结果.num[i]表示数i在数列中出现了几次. 对于数i,要么删i,要么删i-1,只有这两种情况,且子问题还是一样的思路.那么很显然递推一下就行了:f[i]=max(f[i-1],f[i-2]+i*num[i]); 这里技巧在于:为了防止麻烦,干脆就所有数的出现次数都记录一下,然后直接从2推到100000(类似于下标排序),就不用排序了,也不用模拟删除操作了.这一技巧貌似简单,但实际上临场想出来也需要点水平. #include<iostrea

三维递推dp Logo Turtle CodeForces - 132C

https://vjudge.net/problem/CodeForces-132C 题意:   F表示向前走,T表示向后转,有N次修改字符的机会,问最多能走多远 思路:dp[ i ][ j ][ d ]表示前i个字符修改了j次,走了k长度,当前朝向是d的状态的最大长度 所以就可以递推一个关系式,分第i个字符为‘F‘ or ‘T‘时 然后多维递推dp就是当前 i.j都是由 老i.j递推出来的,即 i-1,j-k,其实就是记忆化暴力. 注意:要用max就得先全部初始化为-inf,然后dp[0][0

D. Caesar&#39;s Legions 背包Dp 递推DP

http://codeforces.com/problemset/problem/118/D 设dp[i][j][k1][k2] 表示,放了i个1,放了j个2,而且1的连续个数是k1,2的连续个数是k2 如果这样写,用dfs写是很简单的.但是超时,我记忆化不到 如果用递推写,对于每一个状态,更新到下一个状态. 如果放的是1,那么新的状态是dp[i + 1][j][k1 + 1][0]也就是,用多了一个1,而且连续的个数也增加了.同时,2的连续个数就打破了,变成了0 这种枚举旧状态,更新下一个状态

Codeforces Round #564(div2)

Codeforces Round #564(div2) 本来以为是送分场,结果成了送命场. 菜是原罪 A SB题,上来读不懂题就交WA了一发,代码就不粘了 B 简单构造 很明显,\(n*n\)的矩阵可以按照这个顺序排列 然后根据\(n\)的大小搞一搞就好了 #include<cstdio> #include<cctype> #include<cstring> #include<algorithm> #include<iostream> #incl

codeforces round #257 div2 C、D

本来应该认真做这场的,思路都是正确的. C题,是先该横切完或竖切完,无法满足刀数要求,再考虑横切+竖切(竖切+横切), 因为横切+竖切(或竖切+横切)会对切割的东西产生交叉份数,从而最小的部分不会尽可能的大. 代码如下,虽然比较长.比较乱,但完全可以压缩到几行,因为几乎是4小块重复的代码,自己也懒得压缩 注意一点,比如要判断最小块的时候,比如9行要分成2份,最小的剩下那份不是9取模2,而应该是4 m/(k+1)<=m-m/(k+1)*k          #include<bits/stdc+

codeforces Round #250 (div2)

a题,就不说了吧 b题,直接从大到小排序1-limit的所有数的lowbit,再从大到小贪心组成sum就行了 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #define N 200000 6 using namespace std; 7 int pos[N],a[N],s[N],f[N],la[N],b[N],i,j,k,ans,n,p

hdu 1284 钱币兑换问题 (递推 || DP || 母函数)

钱币兑换问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5069    Accepted Submission(s): 2868 Problem Description 在一个国家仅有1分,2分,3分硬币,将钱N兑换成硬币有很多种兑法.请你编程序计算出共有多少种兑法. Input 每行只有一个正整数N,N小于32768. Outpu

Codeforces Round#320 Div2 解题报告

Codeforces Round#320 Div2 先做个标题党,骗骗访问量,结束后再来写咯. codeforces 579A Raising Bacteria codeforces 579B Finding Team Member codeforces 579C A Problem about Polyline codeforces 579D "Or" Game codeforces 579E Weakness and Poorness codeforces 579F LCS Aga

Codeforces Round #254(div2)A

很有趣的题.想到了就非常简单,想不到就麻烦了. 其实就是一种逆向思维:最后结果肯定是这样子: WBWBWBWB... BWBWBWBW... WBWBWBWB... ... 里面有“-”的地方改成“-”就行了. 但是我开始是正着想的,想每个点怎么处理,这还要看它周围点的状态,越想越麻烦... 这题中体现的正难则反的逆向思维很值得学习. #include<iostream> #include<cstdio> #include<cstdlib> #include<cs