[Ybt Gold Medal Navigation 8-3-2] Evaluation of Sequence

Sequence evaluation

Topic link: ybt gold medal navigation 8-3-2

General idea

Give a function not more than m-1 times, give the value of y when x is 0~m-1, and then find the value of y when x is k.

Ideas

This question will naturally think of Lagrangian interpolation when you see the function.

But you will see that it has a large range, n 2 n^2n2 is not passable.

But you will find that it has a special place: the given points are continuous, and xi = i x_i=ixi=i

Then you consider whether you can simplify the formula.
First take out the formula:
f (k) = ∑ i = 1 n (yi ∏ i ≠ jk − xjxi − xj) f(k)=\sum\limits_{i=1}^{n}(y_i\prod \limits_{i\neq j}\dfrac{k-x_j}{x_i-x_j})f(k)=i=1n( andii=jxixjkxj)
After thatxi = i x_i = ixi=i
f ( k ) = ∑ i = 1 n ( y i ∏ i ≠ j k − j i − j ) f(k)=\sum\limits_{i=1}^{n}(y_i\prod\limits_{i\neq j}\dfrac{k-j}{i-j}) f(k)=i=1n( andii=jijkj)
The inequality condition of the cumulative multiplication is very annoying, so we separate it and multiply it by two cumulative multiplications:
f (k) = ∑ i = 1 n (yi ∏ 1 ≤ j <ik − ji − j ∏ i <j ≤ nk − ji − j) f(k)=\sum\limits_{i=1}^{n}(y_i\prod\limits_{1\leq j<i}\dfrac{kj}{ij}\prod\limits_{i <j\leq n}\dfrac{kj}{ij})f(k)=i=1n( andi1j<iijkji<jnijkj)
Then here we find that the numerator part can be solved by the prefix product and the suffix product respectively.

Then look at the denominator, you will find that it is two factorials.

Then you can preprocess these three things and you can use them.

When dealing with factorial, we can calculate its inverse in advance.
Then don't reverse the inverse element one by one. You can get the T, you can find the largest inverse element, and then multiply it back every time, you can get the smaller factorial inverse element.

and also.
Don't think that my title is wrong.
What is given is from 0 ∼ m − 1 0\sim m-10m1 , the title is problematic, even the sample is wrong.
The correct sample output should be9 99 instead of7 77

Then I found out here because it was later, so I changed it from 0 00 starts to record the array, operation or something.
The loop range of the above formula also needs to be changed slightly, so I won't write it again here.
(If you don’t know how to change, you can see the code)

Code

#include<cstdio>
#define ll long long
#define mo 998244353

using namespace std;

ll m, k, a[1000001];
ll y[1000001];
ll q[1000001], b[1000001];
ll jc[1000001], ans, now;

ll ksm(ll x, ll y) {
    
    //快速幂求逆元
	if (x < 0) x = (x % mo + mo) % mo;
	
	ll re = 1;
	while (y) {
    
    
		if (y & 1) re = (re * x) % mo;
		x = (x * x) % mo;
		y >>= 1;
	}
	
	return re;
}

int main() {
    
    
	scanf("%lld %lld", &m, &k);
	m--;
	
	q[0] = k - 0;
	scanf("%d", &y[0]);
	for (ll i = 1; i <= m; i++) {
    
    
		scanf("%lld", &y[i]);
		
		q[i] = q[i - 1] * ((k - i + mo) % mo) % mo;//处理分子的前缀积
	}
	
	b[m + 1] = 1ll;
	for (ll i = m; i >= 0; i--) {
    
    //处理分子的后缀积
		b[i] = b[i + 1] * ((k - i + mo) % mo) % mo;
	}
	
	jc[0] = 1ll;//求分母的阶乘
	for (ll i = 1; i <= m; i++)
		jc[i] = jc[i - 1] * i % mo;
	jc[m] = ksm(jc[m], mo - 2);//现在就把分母的阶乘的逆元弄好
	for (ll i = m - 1; i >= 0; i--)
		jc[i] = (jc[i + 1] * (i + 1)) % mo;//不要每个都求逆元,会T
	
	for (ll i = 0; i <= m; i++) {
    
    
		now = y[i];//按照公式乘
		now = (now * (((i - 1 < 0) ? 1 : q[i - 1]) * b[i + 1] % mo)) % mo;
		now = (now * (jc[i] * jc[m - i] % mo)) % mo;
		now = (now * ((m - i) & 1 ? -1 : 1)) % mo;
		if (now < 0) now += mo;
		
		ans = (ans + now) % mo;
	}
	
	printf("%lld", ans);
	
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_43346722/article/details/114123945