2019.12.27日常总结

洛谷P4825

【题意】:
在这里插入图片描述
【思路】: R , C R,C 不大,我们可以用 O ( R 2 × C 2 ) O(R^2 \times C^2) 的算法通过此题。

f i , j f_{i,j} 表示有多少中方法可以到达 ( i , j ) (i,j) ,则:

f i , j = k = 1 i 1 l = 1 j 1 f k , l ( a i , j a k , l ) f_{i,j}=\sum^{i-1}_{k=1} \sum^{j-1}_{l=1} f_{k,l}(a_{i,j} \neq a_{k,l})

时间复杂度正正好是 O ( R 2 × C 2 ) O(R^2 \times C^2) (准确地说,是不到 O ( R 2 × C 2 ) O(R^2 \times C^2) )。

【代码】:

int f[110][110],n;
int a[110][110],m;
const int mod=1e9+7;
int main(){
	scanf("%d%d%d",&n,&m,&a[1][1]);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			scanf("%d",&a[i][j]);
	f[1][1]=1;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			for(int k=i+1;k<=n;k++)
				for(int l=j+1;l<=m;l++)
					if (a[i][j]!=a[k][l])
						f[k][l]=(f[k][l]+f[i][j])%mod;
	printf("%d",f[n][m]);
	return 0;
}

洛谷P4440

【题意】: Little Leticija正在准备编程考试。虽然她已经解决了很多任务,但还有一个任务尚未解决,所以她正在向你寻求帮助。您将获得单词 S S Q Q 个查询。在每个查询中,给出正整数 A A B B C C D D 。假设单词 X X 由单词 S S 中位置 A A B B 之间的字母组成,而单词 S S 中位置 C C D D 之间的字母组成单词 Y Y 。如果你可以以某种方式重新排列单词 Y Y 中的字母并获得单词 X X ,则必须回答DA,否则回答NE

【思路】: 如果单词 Y Y 可以通过重组使其含有单词 X X 这么个子串的话,单词 X X 中所有字母的个数都必须 \leq 单词 Y Y 中该字母的个数。那么问题就转化为了:求 S S 的子串 S [ i . . j ] S[i..j] 中分别有多少个字母a,b,c,d,e...z

直接求当然慢,但是我们可以用前缀和优化。记 s [ i ] [ j ] s[i][j] 表示 S 1 , S 2 , S 3 . . . S i S_1,S_2,S_3...S_i 中有多少个字母 j j ,则 S [ A . . B ] S[A..B] 中含有 s [ B ] [ j ] S [ A 1 ] [ j ] s[B][j]-S[A-1][j] 这么多个字母 j j

当然,我们可以给所有字母重新编号,就像离散化一样,把A压缩成0,把B压缩成1……这样就可以大大减少内存的消耗。

【代码】:

int s[50100][30],l,n,A,B;
int C,D;char str[50100];
int main(){
	freopen("t1.in","r",stdin);
	scanf("%s%d",str+1,&n);
	l=strlen(str+1);
	for(int i=1;i<=l;i++){
		memcpy(s[i],s[i-1],sizeof(s[i]));
		s[i][str[i]-'a']++;
	}
	for(int i=1;i<=n;i++){
		scanf("%d%d",&A,&B);
		scanf("%d%d",&C,&D);
		register bool flag=true;
		for(int j=0;j<26;j++)
			if (s[B][j]-s[A-1][j]>s[D][j]-s[C-1][j]){
				flag=false;break;
			}
		if (flag) puts("DA");
		else printf("NE\n");
	}
	return 0;
}
发布了82 篇原创文章 · 获赞 4 · 访问量 1770

猜你喜欢

转载自blog.csdn.net/ZHUYINGYE_123456/article/details/103757334