题干:

链接:https://ac.nowcoder.com/acm/contest/696/C
来源:牛客网
 

自从上次小w被奶牛踹了之后,就一直对此耿耿于怀。

于是"cow"成为了小w的禁忌,而长得和"cow"很像的"owc"…凡是同时含有"c","w","o"的都进入了他的禁忌名单。

小G想给他送一幅幅长为n个字符的长诗,但是又怕触犯他的禁忌。所以他决定要是诗中出现了他的禁忌就宁可不送,可是...他一写起诗来就忘了一切。

小G想知道他有多少种的诗可能不触犯他的禁忌

注:小G只会用小写字母写诗

输入描述:

一行一个整数n表示诗的长度

输出描述:

一行一个整数表示小G有多少种可能的诗不触犯小W的禁忌,由于可能数也许过大,请对109+7取膜后输出

示例1

输入

3

输出

17570

说明

n=3且包含"c","o","w"的只有6个串,所以答案是26^3-6=17570

备注:


 

对于30%30%的数据满足1≤n≤51≤n≤5

对于100%100%的数据满足1≤n≤105

解题报告:

dp的思路不难想 ,就是dp[i][j] 前i个字符出现了 j 禁忌字符,注意是种,所以递推方程就不难推了。复杂度On。

这题还有logn的做法,直接考虑容斥:答案=C(3,2)*可能含有两个非法字符的方案数-C(3,1)*可能含有一个非法字符的方案数+C(3,0)*不含非法字符的方案数=C(3,2)*pow(25,n) - C(3,1)*pow(24,n) + C(3,0)*pow(23,n);直接快速幂求解,复杂度logn。

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define F first
#define S second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 2e5 + 5;
const ll mod = 1e9+7;
ll dp[MAX][3];
int n;
int main()
{
	cin>>n;
	dp[1][0]=23;dp[1][1]=3;dp[1][2]=0;
	for(int i = 2; i<=n; i++) {
		dp[i][0] = (dp[i-1][0] * 23)%mod;
		dp[i][1] = (dp[i-1][0] * 3 + dp[i-1][1]*24)%mod;
		dp[i][2] = (dp[i-1][1] * 2 + dp[i-1][2]*25)%mod;
	}
	printf("%lld\n",(dp[n][0]+dp[n][1]+dp[n][2])%mod);
	return 0 ;
}