[TJOI2018]教科书般的亵渎

Statement


statement

Solution


经过推导发现答案为:
∑ i = 1 m + 1 [ ∑ j = 1 n − a i − 1 j m + 1 − ∑ j = i m ( a j − a i − 1 ) m + 1 ] \sum_{i=1}^{m+1}\left[\sum_{j=1}^{n-a_{i-1}}j^{m+1}-\sum_{j=i}^m(a_j-a_{i-1})^{m+1}\right] i=1m+1[j=1nai1jm+1j=im(ajai1)m+1]
复杂度瓶颈在 ∑ i = 1 n i k \sum_{i=1}^ni^k i=1nik

对以上和式用扰动法

S ( k , n ) = ∑ i = 1 n i k S(k,n)=\sum_{i=1}^ni^k S(k,n)=i=1nik

S ( k + 1 , n ) = ∑ i = 1 n i k + 1 S(k+1,n)=\sum_{i=1}^ni^{k+1} S(k+1,n)=i=1nik+1
S ( k + 1 , n ) + ( n + 1 ) k + 1 = ∑ i = 1 n ( i + 1 ) k + 1 + 1 S(k+1,n)+(n+1)^{k+1}=\sum_{i=1}^{n}(i+1)^{k+1}+1 S(k+1,n)+(n+1)k+1=i=1n(i+1)k+1+1
S ( k + 1 , n ) + ( n + 1 ) k + 1 = ∑ i = 1 n ∑ j = 0 k + 1 ( k + 1 j ) i j + 1 S(k+1,n)+(n+1)^{k+1}=\sum_{i=1}^n\sum_{j=0}^{k+1}\dbinom{k+1}{j}i^j+1 S(k+1,n)+(n+1)k+1=i=1nj=0k+1(jk+1)ij+1
S ( k + 1 , n ) + ( n + 1 ) k + 1 = ∑ i = 0 k + 1 ( k + 1 i ) S ( i , n ) + 1 S(k+1,n)+(n+1)^{k+1}=\sum_{i=0}^{k+1}\dbinom{k+1}{i}S(i,n)+1 S(k+1,n)+(n+1)k+1=i=0k+1(ik+1)S(i,n)+1
S ( k + 1 , n ) + ( n + 1 ) k + 1 = S ( k + 1 , n ) + 1 + ( k + 1 k ) S ( k , n ) + ∑ i = 0 k − 1 ( k + 1 i ) S ( i , n ) S(k+1,n)+(n+1)^{k+1}=S(k+1,n)+1+\dbinom{k+1}{k}S(k,n)+\sum_{i=0}^{k-1}\dbinom{k+1}{i}S(i,n) S(k+1,n)+(n+1)k+1=S(k+1,n)+1+(kk+1)S(k,n)+i=0k1(ik+1)S(i,n)
S ( k , n ) = ( n + 1 ) k + 1 − 1 − ∑ i = 0 k − 1 ( k + 1 i ) S ( i , n ) ( k + 1 k ) S(k,n)=\dfrac{(n+1)^{k+1}-1-\sum\limits_{i=0}^{k-1}\dbinom{k+1}{i}S(i,n)}{\dbinom{k+1}{k}} S(k,n)=(kk+1)(n+1)k+11i=0k1(ik+1)S(i,n)
发现其为一个 k + 1 k+1 k+1次多项式,拉格朗日插值即可,时间复杂度为 O ( T m 3 ) \mathcal {O}(Tm^3) O(Tm3)

f ( x ) = ∑ i = 1 m + 3 y i ∏ j ≠ i x − x j x i − x j f(x)=\sum_{i=1}^{m+3}y_i\prod_{j\not ={i}}\dfrac{x-x_j}{x_i-x_j} f(x)=i=1m+3yij=ixixjxxj

Code

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 55;
const int P = 1E9 + 7;
int A[MAXN];

inline int qPow(int a, int b) {
	int res = 1;
	for (; b; b >>= 1, a = 1ll * a * a % P)
		(b & 1) && (res = 1ll * res * a % P);
	return res;
}

inline int calc(long long n, int k) {
	if (n <= k + 2)
		return A[n];
	
	int res = 0;
	for (int i = 1;i <= k + 2; ++i) {
		int u = 1, v = 1;
		for (int j = 1;j <= k + 2; ++j)
			if (i != j)
				u = 1ll * u * ((n - j) % P + P) % P,
				v = 1ll * v * (i - j + P) % P;
		u = 1ll * u * qPow(v, P - 2) % P * A[i] % P,
		res = (res + u) % P;
	}
	return res;
	
}

int main(void) {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	
	int testCase = 0;
	cin >> testCase;
	
	while (testCase--) {
		long long n;
		int m = 0, ans = 0;
		cin >> n >> m;
		vector <long long> v(m);
		for (long long& a : v)
			cin >> a;
		sort(v.begin(), v.end());
		
		for (int i = 1;i <= m + 3; ++i)
			A[i] = (A[i - 1] + qPow(i, m + 1)) % P;
		
		for (int i = 0, o = 0;i <= m; ++i) {
			ans = (ans + calc(n - (i ? v[i - 1] : 0), m + 1)) % P, o = 0;
			for (int j = i;j < m; ++j)
				o = (o + qPow(v[j] - (i ? v[i - 1] : 0), m + 1)) % P;
			ans = (ans - o + P) % P;
		}
		
		cout << ans << '\n';
	}
	
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值