[題目記錄]一本通高手訓練-數列

youlv發表於2024-10-12

題意

定義 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;
}


相關文章