題意
定義 n-數列 為滿足以下條件的數列 \({a_i}\) :
- 數列長度不小於 \(3\) , 且每個元素為 \(1\) 到 \(n\) 的整數 .
- 對於任意 \(k \ge 3\) , 有 $ (a_k-a_{k-2})(a_{k-1}-a_{k-2})<0$ .
給出 \(n\) , 求 n-數列 的個數 , 對 \(10^9+7\) 取模 .
\(n\le 10^{500000}\)
時空限制 \(1s,512MB\)
題解
第二個條件的易於理解的說法是 : 每個元素的大小都介於後兩個元素之間 . 而對於每個限制 , 都有兩種情況 , 即 $a_k>a_{k-2}>a_{k-1} $ 或 $a_k<a_{k-2}<a_{k-1} $ .
嘗試手動模擬大小關係 , 發現這些大小關係的限制很緊 , 如圖 :
逐個條件進行推導 , 當我們欽定 \(a_2<a_3\) , 就一定有 $ a_3>a_4$ , $ a_4 <a_5$ 等等 . 也就是說 , 一旦 \(a_2,a_3\) 的大小關係得以確定 , 所有的限制都只剩下一種情況 .
而觀察 \(a_2<a_3\) 情況下的所有大小關係 , 發現這些關係中包含一個完整的鏈 : $ 5>4>1>2>4 $ . \(a_2 > a_3\) 同理 .
因此對於確定的 \(k\) 個不同數字 , 組成一個合法序列的方法有且僅有 \(2\) 種.
對於一個長度為 \(k\) 的 n-數列 , 相當於在 \(n\) 個數字裡選互不相同的 \(k\) 個 , 每種選擇方案對應兩個序列 . 可得答案即為 :
\[2\times\sum_{k=3}^{n} C_n^k\\
=2\times(\sum_{k=1}^{n} C_n^k - C_n^0- C_n^1- C_n^2)
\\
=2\times(2^n-1-n-\frac{n(n-1)}{2})
\]
最後 , 因為要取模 , 所以高精度是沒有必要的 . 分別逐位讀取處理 $n\mod p $ 與 $2^n \mod p $ 即可 .
程式碼
#include<bits/stdc++.h>
#define file(x) freopen(#x ".in","r",stdin),freopen(#x ".out","w",stdout)
#define int long long
#define INF 0x3f3f3f3f
#define INF64 1e18
using namespace std;
constexpr int N=26;
constexpr int p=1e9+7;
int qp(int x,int t){
int res=1;
while(t){
if(t&1) res=res*x%p;
x=x*x%p;
t>>=1;
}
return res;
}
string s;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>s;
int x=0,y=1;
for(int i=0;i<s.length();i++) x=(x*10+s[i]-'0')%p,y=qp(y,10)*qp(2,s[i]-'0')%p;
cout<<2*(y-1-x-x*(x-1)/2%p+2*p)%p;
}