2020 HDU多校 第四场 05-Equal Sentences(思维 + Hash)

题目链接: 05-Blow up the Enemy

Description

题意:给定n个字符串,求可变换字符串使得与原串相比,字符串位置绝对值只差不超过1的个数

Sometimes, changing the order of the words in a sentence doesn’t influence understanding. For example, if we change “what time is it”, into “what time it is”; or change “orz zhang three ak world final”, into “zhang orz three world ak final”, the meaning of the whole sentence doesn’t change a lot, and most people can also understand the changed sentences well.

Formally, we define a sentence as a sequence of words. Two sentences S and T are almost-equal if the two conditions holds:

  1. The multiset of the words in S is the same as the multiset of the words in T.
  2. For a word α, its ith occurrence in S and its ith occurrence in T have indexes differing no more than 1. (The kth word in the sentence has index k.) This holds for all α and i, as long as the word α appears at least i times in both sentences.

Please notice that “almost-equal” is not a equivalence relation, unlike its name. That is, if sentences A and B are almost-equal, B and C are almost-equal, it is possible that A and C are not almost-equal.

Zhang3 has a sentence S consisting of n words. She wants to know how many different sentences there are, which are almost-equal to S, including S itself. Two sentences are considered different, if and only if there is a number i such that the ith word in the two sentences are different. As the answer can be very large, please help her calculate the answer modulo 109+7.

Input

  • The first line of the input gives the number of test cases, T(1≤T≤100). T test cases follow.
  • For each test case, the first line contains an integer n(1≤n≤105), the number of words in the sentence.
  • The second line contains the sentence S consisting of n words separated by spaces. Each word consists of no more than 10 lowercase English letters.
  • The sum of n in all test cases doesn’t exceed 2×105.

Output

For each test case, print a line with an integer, representing the answer, modulo 109+7.

Sample Input

2
6
he he zhou is watching you
13
yi yi si wu yi si yi jiu yi jiu ba yao ling

Sample Output

8
233

Method

  • std用的是DP,令f[i]表示与s[1~i]几乎相等的句子个数,转移到 i 的时候,考虑 i 与 i-1 是否进行交换操作即可(交换需要满足 s[i-1] != s[i])。
  • 但是, 显然(此处省略一年的思考过程)对于一个拥有n个不同字符串的串来说,可变换次数是 f[i] = f[i-1]+f[i-2]。所以可以通过打表的方式先对 1~ n个不同字符串的排列方式数预处理出来。
  • 得到 f[i] 之后,直接遍历串即可,遇到两个相同的字符串即为终止,f[i]*f[j]… 最后即可得到正解。(别忘了取模!!!)

Code

详见注释

#include <bits/stdc++.h>

using namespace std;
#pragma GCC optimize(2)
#define ll long long
const int Max = 1e5+3;
const int mod = 1e9+7;

int T, n, last, tmp;
ll dp[Max], ans;
int main()
{
	dp[1] = 1; dp[2] = 2;
	for(int i=3; i<Max; i++)
		dp[i] = (dp[i-1]+dp[i-2])%mod;		//Hash预处理 
	scanf("%d", &T);
	while(T--)
	{
		scanf("%d", &n);
		char s[101]="", ss[101]="";
		ans = 1; tmp = 0;
		for(int i=0; i<n; i++)
		{
			scanf("%s", s); //cout << s << endl;
			if(strcmp(s, ss) != 0) {
				tmp++; strcpy(ss, s); 
			}
			else {
				ans = (ans * dp[tmp])%mod;	//连乘 
				tmp = 1;
			}
		}
		ans = (ans * dp[tmp])%mod;	//最后记得再乘一次,原因自己想想 
		printf("%lld\n", ans);
	}
	return 0;
}

蒟蒻一只,欢迎指正

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值