HDU6806 Equal Sentences

HDU6806 Equal Sentences 【简单dp】

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:

  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

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 <queue>
#include <cstdlib>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
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 <bits/stdc++.h>//斐波那契 做法 
#include <queue>
#include <cstdlib>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值