当前位置: 首页 > news >正文

AtCoder Beginner Contest 399 D,F 题解

D. Switch Seats

题意

有一个长度为 2 N 2N 2N 的序列 A A A,每个 1 1 1 N N N 的整数出现两次

找到满足以下要求的 ( a , b ) (a,b) (a,b)

  • 1 ≤ a < b ≤ N 1\le a<b \le N 1a<bN

  • 两个 a a a A A A 中的位置不相邻,两个 b b b A A A 中的位置不相邻

  • 执行以下操作任意多次,使得两个 a a a 相邻,两个 b b b 也相邻:

    • 选择一个 a a a,选择一个 b b b,交换它们的位置

多测,共 T T T 组数据

思路

有很多方法,我详细说一下分类讨论:

显然,只有 “ab…ab”“ab…ba”“ba…ab”和"ba…ba" 符合条件

定义以下数组:

p o s i pos_i posipair<int,int> 类型,存储数字 i i i 在序列中两次出现的位置

a d j i adj_i adjivector<int> 类型,大小为 4 4 4,存储每个数字 i i i 相邻的数,下标 0 0 0 表示第一次出现的 i i i 左边的 1 1 1 表示第一次右边, 2 2 2 表示第二次左边, 3 3 3 表示第二次右边,若没有相邻的数,这一位就是 − 1 -1 1

由于 a < b a<b a<b,对于每个 i i i,只考虑比它大的数与它组成的数对:

  • a d j i , 0 > i adj_{i,0}>i adji,0>i,以下情况符合要求,设 x = a d j i , 0 x=adj_{i,0} x=adji,0:“xi…xi"或"xi…ix”

  • a d j i , 1 > i adj_{i,1}>i adji,1>i,设 x = a d j i , 1 x=adj_{i,1} x=adji,1

    • a d j i , 2 = x adj_{i,2}=x adji,2=x

      这种情况显然可以:

      但还有特殊情况:

      • 若另一个 x x x 不在 i 1 i_1 i1 前并且不在 i 2 i_2 i2 后,即 p o s i . f i r s t + 2 = p o s i . s e c o n d pos_i.first+2=pos_i.second posi.first+2=posi.second 时,不可以:

      • 若两个 x x x 相邻,即 p o s x . f i r s t + 1 = p o s x . s e c o n d pos_x.first+1=pos_x.second posx.first+1=posx.second 时,不可以:

      • 否则可以:

        注意:不要计算 xixi 的情况,因为这样就重复了

    • a d j i , 3 = x adj_{i,3}=x adji,3=x 可以

  • 其它情况都不可以

C++ 代码

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
typedef pair<int,int> pii;
const int maxn=400005;
int v[maxn];
vector<int> adj[maxn];
pii pos[maxn];
void solve(){
	int n;
	cin>>n;
    
    //清空
	for(int i=1;i<=n;i++){
		pos[i].first=pos[i].second=0;
		adj[i].clear();
	}
    
	for(int i=1;i<=2*n;i++){
		cin>>v[i];
		if(pos[v[i]].first==0) pos[v[i]].first=i;
		else pos[v[i]].second=i;
	}
	for(int i=1;i<=2*n;i++){
		adj[v[i]].pb(v[i-1]==0?-1:v[i-1]);
		adj[v[i]].pb(v[i+1]==0?-1:v[i+1]);
	}
    
	int ans=0;
	set<pii> st;
	for(int i=1;i<=n;i++){
		if(pos[i].first+1==pos[i].second) continue;//相邻直接跳过
		if(adj[i][0]>i){
			if(adj[i][2]==adj[i][0]||adj[i][3]==adj[i][0]){
				ans++;
			}
		}
		if(adj[i][1]>i){
			if(adj[i][1]==adj[i][2]){
				if(pos[i].first+2==pos[i].second){
					if(adj[i][2]!=adj[i][3]){
						//不可以
					}else{
						ans++;
					}
				}else if(pos[adj[i][1]].first+1==pos[adj[i][2]].second){
					//不可以
				}else{
					ans++;
				}
			}else if(adj[i][3]==adj[i][1]){
				ans++;
			}
		}
	}
	cout<<ans<<endl;
}
int main(){
	int32_t T;
	cin>>T;
	while(T--){
		solve();
	}
	return 0;
}

F. Range Power Sum

题意

给你 N , K N,K N,K 和序列 A A A,求出 ∑ 1 ≤ l ≤ r ≤ N ( ∑ l ≤ i ≤ r A i ) K   m o d   998244353 \displaystyle \sum_{1\le l \le r \le N}(\sum_{l\le i\le r}^{A_i})^K \bmod 998244353 1lrN(lirAi)Kmod998244353 的值.

思路

我们先不管取模

首先,看到了区间求和,不难想到前缀和,即定义 S i = ∑ x = 1 i A x S_i=\sum_{x=1}^i A_x Si=x=1iAx

原式转化为 ∑ 1 ≤ l ≤ r ≤ N ( S r − S l − 1 ) K \displaystyle \sum_{1\le l \le r \le N} (S_r-S_{l-1})^K 1lrN(SrSl1)K,但是仍然为 O ( N 2 ) O(N^2) O(N2)

看到了 ( a ± b ) n (a\pm b)^n (a±b)n,迅速想到二项式定理,其中 ( n i ) \displaystyle {n \choose i} (in) 表示组合数 n n n i \displaystyle i i = n ! i ! ( n − i ) ! \displaystyle \frac{n!}{i!(n-i)!} i!(ni)!n!
( a − b ) n = ∑ i = 0 n ( n i ) a i ( − b ) n − i (a-b)^n=\sum_{i=0}^{n} \binom{n}{i}a^i(-b)^{n-i} (ab)n=i=0n(in)ai(b)ni

原式 = ∑ 1 ≤ l ≤ r ≤ N ∑ i = 0 K ( K i ) S r i ( − S l − 1 ) K − i = ∑ l = 1 N ∑ r = l N ∑ i = 0 K ( K i ) S r i ( − S l − 1 ) K − i = ∑ r = 1 N ∑ i = 0 K ( K i ) S r i ( ∑ l = 1 r ( − S l − 1 ) K − i ) \begin{matrix} 原式 &= \displaystyle \sum_{1\le l \le r \le N} \sum_{i=0}^{K} \binom{K}{i} S_r^i(-S_{l-1})^{K-i} \\ &=\displaystyle \sum_{l=1}^N\sum_{r=l}^N \sum_{i=0}^{K} \binom{K}{i} S_r^i(-S_{l-1})^{K-i} \\ &=\displaystyle \sum_{r=1}^N\sum_{i=0}^K \binom{K}{i} S_r^i(\sum_{l=1}^r(-S_{l-1})^{K-i}) \end{matrix} 原式=1lrNi=0K(iK)Sri(Sl1)Ki=l=1Nr=lNi=0K(iK)Sri(Sl1)Ki=r=1Ni=0K(iK)Sri(l=1r(Sl1)Ki)

此时,我们发现 ∑ l = 1 r ( − S l − 1 ) K − i \sum_{l=1}^r(-S_{l-1})^{K-i} l=1r(Sl1)Ki 是可以预处理的,定义 p x p_x px 初始值为 ∑ l = 1 r ( − S l − 1 ) x \sum_{l=1}^r(-S_{l-1})^x l=1r(Sl1)x,对于每个 r r r 的每个 i i i 的操作结束后, p K − i = p K − i − S r − 1 K − i p_{K-i}=p_{K-i}-S_{r-1}^{K-i} pKi=pKiSr1Ki p K − i p_{K-i} pKi 就变成了 ∑ l = 1 r − 1 ( − S l − 1 ) K − i \sum_{l=1}^{r-1}(-S_{l-1})^{K-i} l=1r1(Sl1)Ki

则原式 = ∑ r = 1 N ∑ i = 0 K ( K i ) S r i ⋅ p K − i \displaystyle \sum_{r=1}^N\sum_{i=0}^K \binom{K}{i} S_r^i·p_{K-i} r=1Ni=0K(iK)SripKi,时间复杂度 O ( N K ) O(NK) O(NK),可以通过

再来考虑组合数计算,由于 K ≤ 10 K \le 10 K10 ,直接计算,无需预处理:

int C(int n,int k){
	int res=1;
	for(int i=n;i>=k+1;i--) res*=i;
	for(int i=1;i<=n-k;i++) res/=i;
	return res;
}

接下来考虑取模:

由于 p x p_x px 可能变成负数,而C++自带取模结束后可能为负数(如 − 3   m o d   5 = 2 -3 \bmod 5=2 3mod5=2,但程序会告诉你 − 3   m o d   5 = − 3 -3 \bmod 5=-3 3mod5=3),所以取模过程如下:

p[x]=(p[x]%MOD+MOD)%MOD

最后考虑乘方,由于快速幂比较好写,所以直接用了:

int pw(int a,int b){
	int res=1;
	while(b){
		if(b&1) res=res*a%MOD;
		a=a*a%MOD;
		b>>=1;
	}
	return res;
}

C++ 代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MOD=998244353;
const int maxn=200005;
int n,k;
int v[maxn],s[maxn];
int p[15];
int pw(int a,int b){
	int res=1;
	while(b){
		if(b&1) res=res*a%MOD;
		a=a*a%MOD;
		b>>=1;
	}
	return res;
}
int C(int n,int k){
	int res=1;
	for(int i=n;i>=k+1;i--) res*=i;
	for(int i=1;i<=n-k;i++) res/=i;
	return res;
}
signed main(){
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		cin>>v[i];
		s[i]=(v[i]+s[i-1])%MOD;
	}
	for(int i=0;i<=k;i++){
		for(int j=0;j<n;j++){
			p[i]=(p[i]+pw(-s[j],i))%MOD;
			p[i]=(p[i]+MOD)%MOD;
		}
	}
	int ans=0;
	for(int r=n;r>=1;r--){
		for(int i=0;i<=k;i++){
			ans=(ans+C(k,i)*pw(s[r],i)%MOD*p[k-i]%MOD)%MOD; 
			ans=(ans+MOD)%MOD;
			p[k-i]=(p[k-i]-pw(-s[r-1],k-i))%MOD;
			p[k-i]=(p[k-i]+MOD)%MOD;
		}
	}
	cout<<ans<<endl;
	return 0;
}
http://www.dtcms.com/a/113564.html

相关文章:

  • 对迭代器模式的理解
  • Arduino示例代码讲解:Knock Sensor 敲击感知器
  • 每日一题(小白)模拟娱乐篇14
  • BN测试和训练时有什么不同, 在测试时怎么使用?
  • 【C++项目】从零实现RPC框架「四」:业务层实现与项目使用
  • 【51单片机】2-7【I/O口】点亮数码管
  • 线程池的工作原理
  • 线代[12]|《高等几何》陈绍菱(1984.9)(文末有对三大空间的分析及一个合格数学系毕业生的要求)
  • Python 语法学习 1(类比 java 学习)-附Python 中 self
  • 前端用用jsonp的方式解决跨域问题
  • [ICLR 2025]Biologically Plausible Brain Graph Transformer
  • Reids 的io并发模型
  • 程序化广告行业(60/89):算法优化与DSP系统实例解析
  • Linux系统程序设计:从入门到高级Day03
  • 第八章:流量治理_《凤凰架构:构建可靠的大型分布式系统》
  • DDPM 做了什么
  • 2007-2019年各省地方财政其他支出数据
  • 格式工厂怎样插入内置音频文件
  • 硬件工程师面试问题(五):蓝牙面试问题与详解
  • 在响应式网页的开发中使用固定布局、流式布局、弹性布局哪种更好
  • vllm作为服务启动,无需额外编写sh文件,一步到位【Ubuntu】
  • 『Linux_网络』 第一章 网络基础概念
  • 分表字段选择策略:以电商交易订单为例的最佳实践
  • Java项目之基于ssm的怀旧唱片售卖系统(源码+文档)
  • 大数据时代的隐私保护:区块链技术的创新应用
  • 通过构造函数和几何条件,研究了不同函数的最近点存在性、性质及单调性
  • ZKmall开源商城多云高可用架构方案:AWS/Azure/阿里云全栈实践
  • 紧急更新!MinIO发布RELEASE.2025-04-03T14-56-28Z版本,修复高危漏洞CVE-2025-31489,用户需立即升级!
  • raft协议中一条数据写入流程
  • Java 实现插入排序:[通俗易懂的排序算法系列之三]