1. 程式人生 > >ARC 071 F Infinite Sequence - dp - 字首和

ARC 071 F Infinite Sequence - dp - 字首和

題目大意:有多少個無限長的由{1,2,⋯,n}組成的序列a1,a2,…滿足以下條件?
第n個及以後的元素是相同的,即若i,j≥n,ai=aj。
對於每個元素i,緊隨第i個元素後的ai個元素是相同的,即若i<j<k≤i+ai,aj=ak。
題解:
顯然如果某個數字a[i]=x>1,要麼i+1到i+x全是1,要麼從a[i+1]=y開始到結束全都是y。(換言之一個合法序列只要有兩個相鄰的大於1的數字那麼這個序列就到此為止了)
那麼列舉最後一個有這種效果的i,(即從a[i]>1且a[i+1]>1)或者不存在這種情況下的最後一個大於1的位置。記f[i]表示最後一個>1的數字是a[i],並且之前不存在兩個相鄰的數字>1。列舉上一個>1的數值(或者乾脆i就是第一個),那麼這個x只能放到一個字首裡面(或者乾脆放不了),這個用一個字首和優化字首和優化dp即可。最後用f算答案。

#include<bits/stdc++.h>
#define gc getchar()
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define mod 1000000007
#define db double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" " #define ln <<endl using namespace std; typedef pair<int,int> pii; typedef set<int>::iterator sit; inline int inn() { int x,ch;while((ch=gc)<'0'||ch>'9'); x=ch^'0';while((ch=gc)>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^'0'
);return x; } #define P(x) (x>=mod?x-=mod:0) const int N=1000010;int f[N],s[N],ss[N]; int main() { int n=inn(),ans=1,m=(n-1ll)*n%mod; rep(i,1,n) f[i]=(i>=3?ss[i-3]:0)+1,P(f[i]),s[i]=s[i-1]+f[i],P(s[i]),ss[i]=ss[i-1]+s[i],P(ss[i]); ans+=(n-1ll)*f[n]%mod,P(ans);rep(i,1,n-1) ans+=(lint)m*f[i]%mod,P(ans);return !printf("%d\n",ans); }