2789: 上决╇ф的战争
Time Limit: 1000 MS Memory Limit: 65536 KBTotal Submit: 14 Accepted: 1 Page View: 38
Submit Status Discuss
Description
上决╇ф及其手下锐龙、皓龙、速龙、羿龙、毒龙、闪龙等CPU,以最高频率,杀到了Alpha Ceph所在地。但是Alpha Ceph的洞穴门,是一个十分强大的密码门。这个密码门和斐波那契字符串相关,斐波那契字符串见下图:
F(n)=⎧⎪⎨⎪⎩0n=01n=1F(n−1)+F(n−2)n≥2
n |
---|
F(n) |
---|
0 |
0 |
1 |
1 |
2 |
10 |
3 |
101 |
4 |
10110 |
5 |
10110101 |
6 |
1011010110110 |
7 |
101101011011010110101 |
8 |
1011010110110101101011011010110110 |
9 |
1011010110110101101011011010110110101101011011010110101 |
Alpha Ceph的门上就贴了一个01字符串,只要输出这个字符串在第n
位斐波那契字符串中出现的次数,就能开带Alpha Ceph的大门,击杀Alpha Ceph!
Input
输入第一行,包含一个整数n
,(1≤n≤100),表现需要询问第n个斐波那契字符串。
第二行,包含一个长度不超105
的01字符串,表示被查询的字串。
Output
输出一个整数,为输入的01串在第n
个斐波那契串中出现的次数。结果对264
取模。
6
10
6
101
5
4
Source
Tags
分析 :
第n个字符串,是由第n-1个字符串和第n-2个字符串拼接而成,其贡献为前两个
字符串的贡献与拼接产生的贡献之和。
设题目给出的01串长度为k,那么计算拼接产生的字符串只需要拼接第n-1个的后
k-1个字符和第n-2个前k-1字符即可。在拼接成的字符串中用KMP即可找到该串的贡献。
这样就得到了一个递推的关系。只需要维护每个字符串的前k-1个字符和后k-1个字符。
需要注意的是因为题目中模的是2^64,所以需要使用unsigned long long 。
代码如下:
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <queue> #include <vector> using namespace std; typedef long long LL; const int MAXN=2e5+10; string ll[110]; //每个串的前k-1个字符 string rr[110]; //每个串的后k-1个字符 unsigned long long ans; unsigned long long x; unsigned long long now; unsigned long long num[2][110];//计算串中0和1在第n个串中的数量,用于处理题目所给的01串长度为1的情况 LL n; string r; int Next[MAXN]; void getNext(string T,int tlen) { int j, k; j = 0; k = -1; Next[0] = -1; while(j < tlen) if(k == -1 || T[j] == T[k]) Next[++j] = ++k; else k = Next[k]; } int KMP_Count(string S,int slen,string T,int tlen) { int ans = 0; int i, j = 0; if(slen == 1 && tlen == 1) { if(S[0] == T[0]) return 1; else return 0; } getNext(T,tlen); for(i = 0; i < slen; i++) { while(j>=0 && S[i] != T[j]) j = Next[j]; if(j==-1||S[i] == T[j]) j++; if(j == tlen) { ans++; j = Next[j]; } } return ans; } void init() { ll[0]="0"; rr[0]="0"; ll[1]="1"; rr[1]="1"; num[0][0]=1; //0的数量在第0个串中是1 num[0][1]=0; num[1][0]=0; num[1][1]=1; for(int i=2;i<=100;i++) { num[0][i]=num[0][i-1]+num[0][i-2]; num[1][i]=num[1][i-1]+num[1][i-2]; } } int main() { int st,cha,st2; init(); while(cin>>n) { cin>>r; x=0; int k=r.size(); if(k==1) { cout<<num[r[0]-'0'][n]<<endl; continue; } for(int i=2;i<=n;i++) { ll[i]=ll[i-1].substr(0,k-1); if(ll[i-1].size()<k-1) { cha=k-1-ll[i-1].size(); ll[i]+=ll[i-2].substr(0,cha); } if(rr[i-2].size()>=k-1) { st=rr[i-2].size()-(k-1); rr[i]=rr[i-2].substr(st,k-1); } else { rr[i]=rr[i-2]; cha=k-1-rr[i-2].size(); if(cha>0) { if(rr[i-1].size()>=cha) st2=rr[i-1].size()-cha; else st2=0; rr[i]=rr[i-1].substr(st2,cha)+rr[i]; } } } deque<LL>d; d.push_front(0); d.push_front(0); for(int i=2;i<=n;i++) { x=0; x+=d.front(); x+=d.back(); if(rr[i-1].size()>=k-1) st=rr[i-1].size()-(k-1); else st=0; string now=rr[i-1].substr(st,k-1)+ll[i-2].substr(0,k-1); x+=KMP_Count(now,now.size(),r,r.size()); if(d.size()==2) { d.pop_back(); d.push_front(x); } } cout<<x<<endl; } return 0; }