(蒟蒻第一次写题解,望大家支持!)
分析
这题题目看上去就很深奥
求什么大家应该都懂了,所以直接进入正题。
首先分析 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 2i−1。
因此,我们可以通过递推的方式,不断地将当前的答案乘上 2 i − 1 2 ^ i - 1 2i−1。
验算一下,当 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:蒟蒻第一次写题解,有什么写得不清楚的,欢迎大家提出意见!谢谢!