NC14731 逆序对

题目

题目描述

求所有长度为 n01 串中满足如下条件的二元组个数:
设第 i 位和第 j 位分别位 aiaj (i<j) ,则 ai=1,aj=0
答案对1e9+7取模。

输入描述

输入一个 n

输出描述

输出答案对1e9+7取模

示例1

输入

3

输出

6

说明

img

备注

n1018

题解

知识点:计数dp,运算优化。

推个公式,设f(n) 是长度为 n 时的逆序对总数,推导如下:

因为长度加一,则可以认为首位 10n1 情况的排列组合。由于 10 两种情况,那么 f(n1) 会出现两次; 1n1 所有情况的 0 都会产生一组逆序对,所以只要求出 n10 出现次数,一共有 2n1 种长度为 n1 的串数字,则数字总数是 (n1)2n1 ,注意到 10 各占一半,则 0 的总数是 (n1)2n2

综上有 f(n)=2f(n1)+(n1)2n2,解递推得公式 f(n)=n(n1)22n2

用快速幂运算,注意 n=1 的特殊情况,以及取模问题,50000000421(mod 1000000007)

时间复杂度 O(logn)

空间复杂度 O(1)

代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int mod = 1e9 + 7;
ll qpow(ll a, ll k) {
ll ans = 1;
while (k) {
if (k & 1) ans = a * ans % mod;
k >>= 1;
a = a * a % mod;
}
return ans;
}
///用不着分治,解递推得到通项
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
ll n;
cin >> n;
int ans = (n % mod) * ((n - 1) % mod) % mod * 500000004 % mod * qpow(2, max(n - 2, 0LL)) % mod;
cout << ans << '\n';
return 0;
}
posted @   空白菌  阅读(43)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示