D - We Like AGC
Time Limit: 2 sec / Memory Limit: 1024 MB
Score : 400400 points
Problem Statement
You are given an integer NN. Find the number of strings of length NN that satisfy the following conditions, modulo 109+7109+7:
- The string does not contain characters other than
A
,C
,G
andT
. - The string does not contain
AGC
as a substring. - The condition above cannot be violated by swapping two adjacent characters once.
Notes
A substring of a string TT is a string obtained by removing zero or more characters from the beginning and the end of TT.
For example, the substrings of ATCODER
include TCO
, AT
, CODER
, ATCODER
and (the empty string), but not
AC
.
Constraints
- 3≤N≤1003≤N≤100
Input
Input is given from Standard Input in the following format:
NN
Output
Print the number of strings of length NN that satisfy the following conditions, modulo 109+7109+7.
Sample Input 1 Copy
3
Sample Output 1 Copy
61
There are 43=6443=64 strings of length 33 that do not contain characters other than A
, C
, G
and T
. Among them, only AGC
, ACG
and GAC
violate the condition, so the answer is 64−3=6164−3=61.
Sample Input 2 Copy
4
Sample Output 2 Copy
230
Sample Input 3 Copy
100
Sample Output 3 Copy
388130742
Be sure to print the number of strings modulo 109+7109+7.
题意:
给你一个数字N,N的范围是3~100
让你求出有多少种可能的字符串,使之只包括这四种字符 A
, C
, G
and T
.
并且字符串不含有“AGC”这个子串,并且仅交换一次相邻的字符也不含有“AGC”这个子串。
思路:
我们根据第一个样例就可以看出N=3的所有情况。
因为我们考虑的是DP的写法,先思考如何定义状态,
我们通过思考可以知道我们从N=3转到N=4的状态的时候,我们要考虑整个字符串的后3个字符才可以确定最后一位能不能加上我们在转移的字符,
那么我们不妨在定义状态的时候就把整个字符串的后3位字符都存下来。
所以我们定义状态如下:
DP[ len ][i] [ j ] [ k ] = 长度为len的字符串中,后三位字符串依次是ijk的字符串有多少种。
这里因为只有四种字母,我们不妨给四个字符进行用数码编号表示,以此来简化我们的程序编写;
我们按照字典序把{'A','C','G','T'}; 编为 0 1 2 3.
那么我们现在从N=4开始考虑,
我们知道以下几种情况是不能满足条件的
后三位是 我们不能接上
*AG C
*AC G
*GA C
A*G C
AG* C
我们只需要在转移的时候,把这5种会产生不符合条件的字符串给删除掉(即不计入计数)
就可以顺利的推出答案了。
具体转移的细节见代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define rt return
#define dll(x) scanf("%I64d",&x)
#define xll(x) printf("%I64d\n",x)
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define db(x) cout<<"== [ "<<x<<" ] =="<<endl;
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll powmod(ll a,ll b,ll MOD){ll ans=;while(b){if(b%)ans=ans*a%MOD;a=a*a%MOD;b/=;}return ans;}
inline void getInt(int* p);
const int maxn=;
const int inf=0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
int n;
const ll mod = 1e9+7ll;
ll dp[][][][];
char c[]={'A','C','G','T'};
int main()
{
//freopen("D:\\common_text\\code_stream\\in.txt","r",stdin);
//freopen("D:\\common_text\\code_stream\\out.txt","w",stdout);
// gbtb*/
cin>>n;
string temp="";
int num=;
// repd(i,0,3)
// {
// temp[0]=c[i];
// repd(j,0,3)
// {
// temp[1]=c[j];
// repd(k,0,3)
// {
// temp[2]=c[k];
// cout<<num++<<" ";
// cout<<temp<<endl;
// }
// }
// }
// char c[6]={'A','C','G','T'};
repd(i,,)
{
repd(j,,)
{
repd(k,,)
{
dp[][i][j][k]=;
}
}
}
dp[][][][]=;
dp[][][][]=;
dp[][][][]=;
ll cnt=0ll;
repd(len,,n)
{
repd(i,,)
{
repd(j,,)
{
repd(k,,)
{
cnt=0ll; repd(ii,,)
{
repd(jj,,)
{
repd(kk,,)
{
//{'A','C','G','T'};
if(jj==i&&kk==j)
{
if(k==&&kk==&&jj==)
{ }else if(k==&&kk==&&jj==)
{ }else if(k==&&kk==&&jj==)
{ }else if(k==&&kk==&&ii==)
{ }else if(k==&&jj==&&ii==)
{ }else
{
cnt+=dp[len-][ii][jj][kk];
cnt=(cnt+mod)%mod;
}
} }
}
}
cnt=(cnt+mod)%mod;
dp[len][i][j][k]=cnt;
// printf("%d %d %d %lld\n",i,j,k,cnt);
}
}
}
}
ll ans=0ll;
repd(i,,)
{
repd(j,,)
{
repd(k,,)
{
ans+=dp[n][i][j][k];
ans=(ans+mod)%mod;
} }
}
cout<<ans<<endl;
return ;
} inline void getInt(int* p) {
char ch;
do {
ch = getchar();
} while (ch == ' ' || ch == '\n');
if (ch == '-') {
*p = -(getchar() - '');
while ((ch = getchar()) >= '' && ch <= '') {
*p = *p * - ch + '';
}
}
else {
*p = ch - '';
while ((ch = getchar()) >= '' && ch <= '') {
*p = *p * + ch - '';
}
}
}