NC14731 逆序对

逆序对

https://ac.nowcoder.com/acm/problem/14731

题意

在长度为n的01串中,若第i位=1,第j位=0,i<j,则成这是一对逆序对,求所有的长度为n的01串中一共能出现多少逆序对

思路一

枚举逆序对出现位置的方案

图片说明 为例,逆序对可能的存在方案有:
图片说明图片说明图片说明 三种方案(图片说明 ),每种方案中含一个图片说明 代表未知数字,这个未知数字又只能是0或1,所以共有图片说明 个逆序对

可能存在的疑惑
只有我这种菜鸡会有这样的疑惑吧
可能会想,在图片说明图片说明两个逆序对存在方案种,会存在某01串同时满足两种方案,比如这里的图片说明 ,这样计算会不会把一个逆序对计算两边呢?

其实图片说明 中的第一个1和0、第二个1和0各自是一个逆序对,分别对应了那两种逆序对存在方案,也就是说,一个逆序对存在方案只记录了图片说明两个逆序对中的一个,所以并不会出现重复计算的情况

思路二(并不完善,不会写了)

找规律
说一下我找规律的过程

图片说明 为所有长度为n的01串中逆序对的个数

图片说明 时:图片说明

0开头 1开头
0 1

图片说明 时: 图片说明

0开头 1开头
00 10
01 11

图片说明 时: 图片说明

0开头 1开头
000 100
001 101
010 110
011 111

不难发现,每当图片说明 时,新的01串就是在原有的01串左边加上0或1,让01串数量翻倍。数量翻倍以后,因为是在原有的01串的最左边加了一个数字,所有右边部分仍然有原先两倍多的逆序列。同时,因为有一部分新的01串时在旧01串左边加了1,这会根据原有01串中0的数量增加新的逆序对。
也就是说,图片说明
因为0和1出现的次数其实是一样的,所以我们的公式可以写为:
图片说明

运用待定系数法构造等比数列以后 应该 可以得到f(n)关于n的公式 但是我不会,只能交给聪明的你了

代码

*需要用到快速幂取余

#include <iostream>

#define ull unsigned long long
using namespace std;

const ull m = 1e9 + 7;

ull myPow(ull a, ull x, ull mod) {
    ull res = 1;
    while (x) {
        if (x & 1) res = res * a % mod;
        a = a * a % mod;
        x >>= 1;
    }
    return res;
}

int main() {
    ull n;
    cin >> n;
    if (n == 2) {
        cout << "1";
        return 0;
    }
    ull a = ((n % m) * ((n - 1) % m)) % m;
    ull b = myPow(2, n - 3, m);
    cout << (a * b) % m;
}
全部评论

相关推荐

码农索隆:这种hr,建议全中国推广
点赞 评论 收藏
分享
05-23 20:31
已编辑
武汉大学 Java
内向的柠檬精在研究求...:注意把武大标粗标大 本地你俩不是乱杀
实习进度记录
点赞 评论 收藏
分享
05-09 12:23
已编辑
华南理工大学 Java
野猪不是猪🐗:给他装的,双九+有实习的能看的上这种厂我直接吃⑨✌们拿它练练面试愣是给他整出幻觉了
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
07-02 14:45
bg是二本双一流硕,目标是Java后端开发岗,投暑期实习0大厂面试,只有极少的大厂测开,可能投的晚加上简历太烂加上0实习?求大佬们给个建议
程序员小白条:别去小厂,初创或者外包,尽量去中小,100-499和500-999,专门做互联网产品的,有公司自研的平台和封装的工具等等,去学习一些业务相关的,比如抽奖,积分兑换,SSO认证,风控,零售等等,目标 Java 后端开发吗?你要不考虑直接走大厂测开?如果技术不行的话,有面试你也很难过的
实习,不懂就问
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务