题目链接: 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:
- The multiset of the words in S is the same as the multiset of the words in T.
- 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;
}
蒟蒻一只,欢迎指正