做题打卡第29天

今天依旧是链表
emmm昨天以为是周日
没发
网课还是很烦
明天决定不上了
今天不多说
看题就ok
题目背景
作为唯一一道有背景的题,此题由出题人基于 @Ecrade_ 的原创题“子集”拓展而来。

“子集”便是本题中 k=n-1k=n−1 的情况。

题目描述
给定一个有 nn 个元素的序列 aa。

定义一个有 xx 个元素的序列 ss 的值为:

\sum \limits _{i=1} ^ x s_i \times \prod \limits _{i=1} ^ x s_i
i=1

x

s
i

×
i=1

x

s
i

将序列 aa 的一个有 xx 个元素的子序列表示为 s = {a_{p_1},a_{p_2},…,a_{p_x}}s={a
p
1


,a
p
2


,…,a
p
x


},其中 pp 为严格单调递增的序列,1 \le p_1 \le p_x \le n1≤p
1

≤p
x

≤n 。

给定整数 kk,定义序列 aa 的一个有 xx 个元素的合法的子序列 ss 需满足 p_x - p_1 \le kp
x

−p
1

≤k。

求序列 aa 的所有合法子序列的值之和对 modmod 取模的值。

输入格式
第一行三个整数,n,k,modn,k,mod 。

第二行 nn 个整数,a_ia
i

输出格式
一行一个整数表示答案对 modmod 取模的值。
原题链接:https://www.luogu.com.cn/problem/P6856
我的答案:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
#define G() Cr = getchar()
#define LL long long
LL Xr, Fr; char Cr;
inline LL rd() {
	Xr = 0, Fr = 1, G();
	while(Cr < '0' || Cr > '9') {if(Cr == '-') Fr = -1; G();}
	while(Cr >= '0' && Cr <= '9') Xr = (Xr<<1) + (Xr<<3) + (Cr&15), G();
	return Xr * Fr;
}
#define MAX_N 1000005
LL n, k, mod;
LL va[MAX_N], f[MAX_N][3], b[MAX_N][3], l[MAX_N], r[MAX_N], ans, s; // 0 -> from left ; 1 -> from right

LL work( LL L, LL R ) {
	if( L == R ) return va[L] * va[L] % mod;
	if( l[L] == l[R] ) return f[R][0];
	LL x, y, A, B;
	x = f[L][1], y = f[R][0];
	A = b[L][1], B = b[R][0];
	return ( x + y + A * y % mod + B * x % mod ) % mod;
}

int main() {
	n = rd(), k = rd(), mod = rd();
	for( int i = 1; i <= n; i++ ) va[i] = rd();
	if(!k) {
		for( int i = 1; i <= n; i++ ) ans = ( ans + va[i] * va[i] ) % mod;
		cout << ans;
		return 0;
	}
	for( int i = 1; i <= n; i++ ) l[i] = ( i - 1 ) / k * k + 1, r[i] = ( ( i - 1 ) / k + 1 ) * k;
	for( int i = 1; i <= n; i++ ) {
		if( i == l[i] ) b[i][0] = va[i], f[i][0] = va[i] * va[i] % mod;
		else {
			f[i][0] = (va[i] * va[i] % mod * ( 1 + b[i-1][0] ) % mod + f[i-1][0] * ( 1 + va[i] ) % mod ) % mod;
			b[i][0] = ( b[i-1][0] * ( 1 + va[i] ) + va[i] ) % mod;
		}
	}
	for( int i = n; i >= 1; i-- ) {
		if( i == r[i] ) b[i][1] = va[i], f[i][1] = va[i] * va[i] % mod;
		else {
			f[i][1] = (va[i] * va[i] % mod * ( 1 + b[i+1][1] ) % mod + f[i+1][1] * ( 1 + va[i] ) % mod ) % mod;
			b[i][1] = ( b[i+1][1] * ( 1 + va[i] ) + va[i] ) % mod;
		}
	}
	for( int i = k + 1; i < n; i++ )
		ans = ( ans + work(i-k,i) - work(i-k+1,i) + mod ) % mod;
	ans = ( ans + work(n-k,n) ) % mod;
	cout << ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值