Equal Sentences
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 298 Accepted Submission(s): 161
Problem Description
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:
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
Source
2020 Multi-University Training Contest 4
问题链接
对句子S中的单词向前移一位或向后移一位或不移得到的两个句子几乎相等,求多少不同的句子,几乎等于S,包括S本身
每个单词的位置都有两种状态,交换和没交换。第i-1位置到第i位置有几种情况:
两单词相同时,有两种:i-1的已交换—>i的不交换,i-1的没交换—>i的不交换。dp[i][0]=(dp[i-1][1]+dp[i-1][0]);
两单词不相同时,有三种:i-1的已交换—>i的不交换,i-1的没交换—>i的不交换,i-1的没交换—>i的交换。
dp[i][1]=dp[i-1][0];
dp[i][0]=(dp[i-1][1]+dp[i-1][0]);
简单dp
AC的C++语言程序如下:
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int main()
{
int t,n;
long long dp[100005][2];
string s1,s2;
cin>>t;
while(t--)
{
cin>>n;
cin>>s1;
memset(dp,0,sizeof(dp));
dp[0][0]=1;dp[0][1]=0;
for(int i=1;i<n;i++)
{
cin>>s2;
if(s1==s2)
dp[i][0]=(dp[i-1][1]+dp[i-1][0])%1000000007;
else {
dp[i][1]=dp[i-1][0];
dp[i][0]=(dp[i-1][1]+dp[i-1][0])%1000000007;
}
s1=s2;
}
cout<< (dp[n-1][0]+dp[n-1][1])%1000000007 <<endl;
}
return 0;
}
吾一开始发现不同的单词前后交换的句子数目符合斐波那契数列,
就直接去重用斐波那契了,结果wa了n发,吾后来才发现句子中间的两个相同的单词不能直接去重,呜呜呜~~
后来把句子分块就可以用了
AC的C++语言程序如下:
//#include //斐波那契 做法
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int main()
{
long long b[100005],ans;
b[0]=1;b[1]=1;b[2]=2;
for(int i=3;i<=100000;i++)
b[i]=(b[i-1]+b[i-2])%1000000007;
int t,n,c;
string a[100005];
cin>>t;
while(t--)
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
c=0;ans=1;
for(int i=1;i<=n;i++)
{
if(a[i]!=a[i-1])c++;
else {ans=(ans*b[c])%1000000007,c=1;}
}
ans=(ans*b[c])%1000000007;
cout<<ans<<endl;
}
return 0;
}