首页 > 其他分享 >[AGC030D] Inversion Sum

[AGC030D] Inversion Sum

时间:2023-09-22 21:01:46浏览次数:36  
标签:operations Inversion perform pw int Sum leq AGC030D dp

Problem Statement

You are given an integer sequence of length $N$: $A_1,A_2,...,A_N$. Let us perform $Q$ operations in order. The $i$-th operation is described by two integers $X_i$ and $Y_i$. In this operation, we will choose one of the following two actions and perform it:

  • Swap the values of $A_{X_i}$ and $A_{Y_i}$
  • Do nothing

There are $2^Q$ ways to perform these operations. Find the sum of the inversion numbers of the final sequences for all of these ways to perform operations, modulo $10^9+7$.

Here, the inversion number of a sequence $P_1,P_2,...,P_M$ is the number of pairs of integers $(i,j)$ such that $1\leq i < j\leq M$ and $P_i > P_j$.

Constraints

  • $1 \leq N \leq 3000$
  • $0 \leq Q \leq 3000$
  • $0 \leq A_i \leq 10^9(1\leq i\leq N)$
  • $1 \leq X_i,Y_i \leq N(1\leq i\leq Q)$
  • $X_i\neq Y_i(1\leq i\leq Q)$
  • All values in input are integers.

先定义 \(dp_{i,j}\) 为 \(a_i<a_j\) 的方案数。

然后发现一次交换会改变所有的 \(dp_{i,j}\)。但是大多的 \(dp_{i,j}\) 都是乘上2,除了 \(x_i\) 和 \(y_i\) 相关的 dp 以外。

所以把 \(dp_{i,j}\) 的定义改为 \(a_i>a_j\) 的概率,然后每次只有 \(O(n)\) 个 dp 值会修改。

#include<bits/stdc++.h>
using namespace std;
const int N=3005,P=1e9+7,iv2=P+1>>1;
int n,q,pw[N],dp[N][N],a[N],x,y,ans,g1[N],g2[N];
int main()
{
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++)
		scanf("%d",a+i);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			dp[i][j]=a[i]>a[j];
	for(int i=pw[0]=1;i<=q;i++)
	{
		pw[i]=pw[i-1]<<1;
		if(pw[i]>=P)
			pw[i]-=P;
	}
	for(int i=1;i<=q;i++)
	{
		scanf("%d%d",&x,&y);
		for(int i=1;i<=n;i++)
			g1[i]=dp[i][x]&1? dp[i][x]+P>>1:dp[i][x]>>1,g2[i]=dp[x][i]&1? dp[x][i]+P>>1:dp[x][i]>>1;
		for(int i=1;i<=n;i++)
		{
			if(i^x&&i^y)
			{
				dp[i][x]=(dp[i][x]&1? dp[i][x]+P>>1:dp[i][x]>>1)+(dp[i][y]&1? dp[i][y]+P>>1:dp[i][y]>>1);
				if(dp[i][x]>=P)
					dp[i][x]-=P;
			}
		}
		for(int i=1;i<=n;i++)
		{
			if(i^x&&i^y)
			{
				dp[x][i]=(dp[x][i]&1? dp[x][i]+P>>1:dp[x][i]>>1)+(dp[y][i]&1? dp[y][i]+P>>1:dp[y][i]>>1);
				if(dp[x][i]>=P)
					dp[x][i]-=P;
			}
		}
		for(int i=1;i<=n;i++)
		{
			if(i^y&&i^x)
			{
				dp[i][y]=(dp[i][y]&1? dp[i][y]+P>>1:dp[i][y]>>1)+g1[i];
				if(dp[i][y]>=P)
					dp[i][y]-=P;
			}
		}
		for(int i=1;i<=n;i++)
		{
			if(i^y&&i^x)
			{
				dp[y][i]=(dp[y][i]&1? dp[y][i]+P>>1:dp[y][i]>>1)+g2[i];
				if(dp[y][i]>=P)
					dp[y][i]-=P;
			}
		}
		dp[x][y]=dp[y][x]=(dp[x][y]+dp[y][x])*1LL*iv2%P;
	}
	for(int j=1;j<n;j++)
	{
		for(int k=j+1;k<=n;k++)
		{
			ans+=dp[j][k];
			if(ans>=P)
				ans-=P;
		}
	}
	printf("%lld",ans*1LL*pw[q]%P);
}

标签:operations,Inversion,perform,pw,int,Sum,leq,AGC030D,dp
From: https://www.cnblogs.com/mekoszc/p/17723351.html

相关文章

  • AtCoder Grand Contest 023 E Inversions
    洛谷传送门AtCoder传送门首先将\(a\)从小到大排序,设\(p_i\)为排序后的\(a_i\)位于原序列第\(p_i\)个位置,\(x_i\)为要填的排列的第\(i\)个数。设\(A=\prod\limits_{i=1}^n(a_i-i+1)\),则\(A\)为排列的总方案数(考虑按\(a_i\)从小到大填即得)。套路地,统......
  • 无涯教程-JavaScript - SUMIF函数
    描述您可以使用SUMIF函数对满足指定条件的范围内的值求和。语法SUMIF(range,criteria,[sum_range])争论Argument描述Required/Optionalrange您要通过条件判断的单元格范围。每个范围中的单元格必须是数字或包含数字的名称,数组或引用。空白和文本值将被忽略。......
  • 无涯教程-JavaScript - SUM函数
    描述SUM函数可添加值。语法SUM(number1,[number2]...)争论Argument描述Required/Optionalnumber1Thefirstnumberyouwanttoadd.Thenumbercanbeavalue,acellreference,oracellrange.Requirednumber2,…Youcanspecifyupto255additionaln......
  • 计算机视觉算法中的视频摘要(Video Summarization)
    引言随着数字视频内容的爆炸式增长,如何高效地获取视频的关键信息成为了一个重要的问题。视频摘要(VideoSummarization)作为计算机视觉领域的一个重要研究方向,旨在通过自动化方法从长时间的视频中提取出关键的、代表性的内容,以便用户能够快速浏览和获取视频的核心信息。本文将介绍视......
  • 38-列表-排序-revered逆序-max_min_sum
               迭代器只能用一次,以时间换空间      ......
  • LeetCode-Java题解 209. Minimum Size Subarray Sum
    题目地址:209.MinimumSizeSubarraySum解题思路:    看到这道题,心里本身是有双指针这个概念的,但是不知道怎么用,脑子里第一反应就是暴力解法,双for一把梭,然后时间就超时了...看了题解才知道滑动窗口这个解法,不禁直呼妙啊!感觉和双指针非常类似,其核心点在于避免了暴力算法的枚......
  • 在PG或HGDB上启用块校验checksum
     瀚高数据库目录环境文档用途详细信息  环境系统平台:Linuxx86-64RedHatEnterpriseLinux7版本:14,N/A 文档用途用途使用checksum,对数据库提供块校验,以发现隐藏的块损坏问题,注意仅适用于原生PG或HGDB企业版,或未使用SM4加密的HGDB安全版。HGDB安全版假如使用了SM4加密,会与che......
  • RocketMQ教程-(4)-领域模型-消费者(Consumer)
    本文介绍ApacheRocketMQ中消费者(Consumer)的定义、模型关系、内部属性、行为约束、版本兼容性及使用建议。定义消费者是ApacheRocketMQ中用来接收并处理消息的运行实体。消费者通常被集成在业务系统中,从ApacheRocketMQ服务端获取消息,并将消息转化成业务可理解的信息,供业务......
  • RocketMQ教程-(4)-领域模型-消费者分组ConsumerGroup
    定义消费者分组是ApacheRocketMQ系统中承载多个消费行为一致的消费者的负载均衡分组。和消费者不同,消费者分组并不是运行实体,而是一个逻辑资源。在ApacheRocketMQ中,通过消费者分组内初始化多个消费者实现消费性能的水平扩展以及高可用容灾。在消费者分组中,统一定义以下消费行......
  • java consumer接口
    参考:https://blog.csdn.net/weixin_44230693/article/details/113847162consuemrvoidaccept(Tt):对给定的参数执行此操作。defaultConsumerandThen(Consumerafter):返回一个组合的Consumer,依次执行操作,然后执行after操作。Consumer接口也称为消费型接口,它消费的数据的数据......