『8.21 模拟赛』冒泡排序 II

题目描述

前一天的冒泡排序对rsw来说太简单了,所以又有了冒泡排序2,给定n,k,q,问:有多少个不同的1~n的排列,能够使得,冒泡排序k趟后,得到一个几乎正确的序列。

一个几乎正确的序列指的是:它的最长上升子序列的长度至少是n-1。

解题思路

思路就是没有思路。。。。

昨天刚刚做过一道冒泡排序的题,有一个结论在这里

每个位置上的数最远是由前面的第k个位置转移过来的,并且题目中要求最长上升子序列最短是n-1的长度,所以只有两种情况:

1) 最终是从小到大排序好的

2)最终是从小到大排序好的序列中选择一段向前循环滚动一个位置或者向后滚动一个位置,这样就有一个数在它不应该在的位置

我们既然正着推不好推,那我们就反着推呗,从每个几乎正确的序列转移到最初的情况。

比如这张图片,k=3。3,4,5,6向前滚动了一次,下面代表着每个位置的数的位置有集中选择,显然,在3前面,每个数都有k+1种选择,然鹅到了3,我们只能把它放在9那里,为什么呢? 如果3在8上,那排完序后3一定跑到6哪里去了,对吧?剩下的数,由于区间长度不过了,他们只能找位置放在最后的地方了,所以是3,2,1。

那么,除了3和最后k个没地方往后放的数以外,所有数都有k+1种放的方法,所以我们先有\((k+1)^\left(n-k-1\right)\)种放的方法,后面的几个数没地方放了,那答案就是\(k!\),由乘法原理可以得到这样的答案总数为\((k+1)^\left(n-k-1\right)×k!\)。假设区间长为i,这样下来,总共有n-k-i+1个地方可以选做区间的开头,所以总答案就是\((k+1)^\left(n-k-1\right)×k!×(n-k-i+1)\)。

向右平移的方法跟这个差不多,按照这个方法也可以推出来。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
ll p[100];
ll n,k,q;
int main(){
    scanf("%lld%lld%lld",&n,&k,&q);
    p[0]=1;
    for(register ll i=1;i<100;i++)p[i]=(p[i-1]*(k+1))%q;
    k=min(k,n);
    ll ans=p[n-k];
    for(register ll i=2;i+k<=n;i++){
        ans=(ans+(ll)(n-k+1-i)*(ll)p[n-k+1-i])%q;
    }
    for(register ll i=3;i+k<=n;i++){
        ans=(ans+(ll)(n-k+1-i)*(ll)p[n-k-1])%q;
    }
    for(register ll i=1;i<=k;i++){
        ans=(ans*i)%q;
    }
    cout<<ans<<endl;
}

原文地址:https://www.cnblogs.com/Fang-Hao/p/9515253.html

时间: 2024-08-30 00:32:40

『8.21 模拟赛』冒泡排序 II的相关文章

『8.20 模拟赛』冒泡排序

题目描述 给定n,k,和一个长度为n的序列,请输出这个序列冒泡排序k次之后的结果. 解题思路 我们观察上面给出的伪代码,可以发现这是一段把代码排序成升序的代码,那我们来考虑一下冒牌排序的几个特征. 一个大的数要向右交换,但是一次交换之后就可以换很多位置,所以换一次就不知道跑到哪里去了,所以很难维护. 一个小的数每次最多和它左边的更大的数交换一次,所以一次最多向左边跑一个位置,比大数不知道好维护到那里去了. 进一步思考,k次交换之后,最多可以向左跑k步,也就是说k+1位置的数最远能跑到1的位置上来

『8.21 模拟赛』Victory

题目描述 迟到大王rsw喜欢V这个字母,因为V代表着victory,当一个数字,从左向右数的时候,没有出现过先递减,再递增的情况,就被称作Victory数. 也就是说,这个数字可以是递增的,也可以是递减的,也可以是先递减再递增的,这个过程中可以出现相邻数字相等的情况,但是,就是不能出现过先递减再递增的情况. 问题是:给定n,问:1~n之间有多少个victory数. 解题思路 我们应该一眼就能看出这是一道数位dp题,一开始用3维dp写,状态不够写挂了...后来改用4维就A了. 我们用dp[ i ]

『8.21 模拟赛』技能大赛

题目描述 rsw因为迟到次数太多被列入黑名单,于是被派去参加陕西妇女儿童技能大赛,大赛中共安排了m个比赛项目,算上rsw在内,共有n位选手报名参加本次比赛.(如rsw,zrx,kh,ljm,cky,大耳朵图图,大头儿子等) 经过m场比赛,组委会发现,每个项目,有且仅有两个人实力超群.(比如穿针引线项目,rsw,ljm独领风骚,健美操项目,cky,cjy风姿绰约). 现在,组委会要推选一些人去参加全国比赛,因为每个项目都必须有人擅长,所以推选的这些人,对于每一个项目,至少要有一个人擅长. 已知,选

『8.20 模拟赛』旋转的多边形

题目链接戳着里!! 题目描述 解题思路 显然,多边形滚动的时候,指定的点一定是绕着某一个顶点旋转的,旋转的半径就是点到顶点的距离,角度就是顶点所在脚的外角. 如下图所示: 那么我们的问题就转化成了求dis和θ了. dis很简单,只要勾股定理就好了. 那θ呢?也很简单喽,只要链接当前顶点的相邻的两个顶点,运用余弦定理求就好啦,注意一下角度值和弧度制就可以了. (不会余弦定理的小伙伴戳这里==>  Wikipedia & 百度百科) 代码 1 #include<iostream> 2

『8.25 模拟赛』外卖 (atcoder 100e)

题目链接 题目描述 众所周知,\(cky\)喜欢点外卖. 已知可选的商品有\(n\)种,\(cky\)由于胃容量问题只能点两份(不能一种点两份).\(cky\)要在防止营养过剩的情况下选择美味度最高的搭配. 具体的,对于每第\(i\)个商品,\(i\)正好是其营养成分,\(s_i\)表示其美味度(商品从\(0\)开始编号). 对于每种搭配\((a,b)\),其营养程度为(\(a|b\)其中\(|\)表示二进制下的按位或),其美味度为\(s_a+s_b\). 即\(cky\)要选择满足\(a|b\

『8.24 模拟赛』ranwen的服务器

题目链接戳这里n(*≧▽≦*)n 题目描述 众所周知,ranwen建造出了强大的服务器网,规模十分庞大,有n个服务器,组成一个树形结构,1号点是总站,但是有时候可能会因为主机被回收,机房断电等事故造成服务器各种GG,现在有m个事件,可能为:1.查询x到根路径上第一个已经挂掉的服务器传输路径 2.x到y路径上的服务器传输路径全挂了.(不存在则输出0) 解题思路 上来先是树剖,然而只过了样例,爆0... 题面上提示了正解是并查集,但是并没有想出来,听完题解瞬间懂了.... 并查集,当然最方便的是合并

11.12 模拟赛T2 冒泡排序图

[问题描述] 有一段使用冒泡排序产生一张图的伪代码如下:function bubbleSortGraph(n, a[]): graph = emptyGraph() repeat swapped = false for i = 1 to n - 1:  if a[i] > a[i + 1]: graph.addEdge(a[i], a[i + 1]) swap(a[i], a[i + 1]) swapped = true until not swapped return graph函数的输入为长

『8.21考试题解及反思』

UNO Description 良心出题人Magolor找到了你,想要和你一起玩桌(mo)游(ni). Magolor: "杀蚂蚁?猪国杀?斗地主?麻将?立体图?哪一个好啊?" 你: "毒瘤出题人!" Magolor伤心了--"我应该给人留下一个良心出题人的印象啊!" 于是Magolor选择了众所周知的UNO.整个周游只使用UNO牌,但完全不按照UNO的规则来打.牌局有3位玩家(你.Magolor.Magolor的好朋友TTL): 每个人将会摸到

NOIP模拟赛 6.29

2017-6-29 NOIP模拟赛 Problem 1 机器人(robot.cpp/c/pas) [题目描述] 早苗入手了最新的Gundam模型.最新款自然有着与以往不同的功能,那就是它能够自动行走,厉害吧. 早苗的新模型可以按照输入的命令进行移动,命令包括‘E’.‘S’.‘W’.‘N’四种,分别对应东南西北.执行某个命令时,它会向对应方向移动一个单位.作为新型机器人,它可以执行命令串.对于输入的命令串,每一秒它会按命令行动一次.执行完命令串的最后一个命令后,会自动从头开始循环.在0时刻时机器人