洛谷P8474 「GLR-R3」立春(【LGR-117】洛谷 8 月月赛 II & GLR R3 div.2 T1)题解

(蒟蒻第一次写题解,望大家支持!)

分析

这题题目看上去就很深奥

求什么大家应该都懂了,所以直接进入正题。

首先分析 n = 2 n = 2 n=2 时和 n = 3 n = 3 n=3 时的情况。

n = 2 n = 2 n=2 时:

  • 序列 [ 1 , 2 ] [1,2] [1,2] 逆序对个数为 0 0 0
  • 序列 [ 2 , 1 ] [2,1] [2,1] 逆序对个数为 1 1 1
  • 答案为 2 0 + 2 1 = 3 2^0 + 2^1 = 3 20+21=3

n = 3 n = 3 n=3 时:

  • 序列第一个数为 1 1 1 时,其对后面两个数无影响,即在这个部分中,答案为 3 3 3
  • 序列第一个数为 2 2 2 时,会和 1 1 1 产生 1 1 1 对逆序对,在 n = 2 n = 2 n=2 的答案的基础上,会乘上一个 2 2 2
  • 序列第一个数为 3 3 3 时,会和 1 , 2 1,2 1,2 产生 2 2 2 对逆序对,在 n = 2 n = 2 n=2 的答案的基础上,会乘上两个 2 2 2

可以发现:无论序列中第一个数是多少,序列中除第一个数外的其它数所组成的排列,其答案一定。

另一个发现:序列中的第一个数是多少会对总的答案产生影响,在刚刚的例子中便是如此。这个产生的影响是多少呢?序列中第一个数会和比它小的数产生逆序对,将后面序列的答案乘上了 2 2 2 的逆序对数量次方。

根据乘法分配律,将乘上的数量相加,为 2 i − 1 2^i - 1 2i1

因此,我们可以通过递推的方式,不断地将当前的答案乘上 2 i − 1 2 ^ i - 1 2i1

验算一下,当 n = 4 n = 4 n=4 时,同样有这个规律。

值得一提的是,处理 2 i 2 ^ i 2i 之时,为了避免溢出,可以设置一个 M O D 2 MOD2 MOD2 数组,记录 2 i 2 ^ i 2i 取模 1 0 9 + 7 10 ^ 9 + 7 109+7 的值。

接下来就可以写出代码了。

AC Code:

#include <iostream>
#define ull unsigned long long

using namespace std;

const ull MOD = 1e9 + 7;
int MOD2[10000001];

int main() {
	int n; cin >> n; MOD2[0] = 1;
	for (int i = 1; i <= n; i++)
		MOD2[i] = (ull)MOD2[i - 1] * 2 % MOD; \\处理MOD2数组
	if (n == 1) {
		cout << 1; return 0;
	} if (n == 2) {
		cout << 3; return 0;
	} //两组特判
   ull ans = 3; //从3开始算
	for (int i = 3; i <= n; i++)
		ans *= MOD2[i] - 1, ans %= MOD; \\递推计算ans
	cout << ans;
	return 0;
}

PS:蒟蒻第一次写题解,有什么写得不清楚的,欢迎大家提出意见!谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值