题目描述

给你一个长度为 $n$ 的序列 $\{a_i\}$ 和一个数 $x$ ,对于任意一个 $1\sim n$ 的排列 $\{p_i\}$ ,从 $1$ 到 $n$ 依次执行 $x=x\ \text{mod}\ a_{p_i}$ ,最终得到一个数。求所有排列中能够得到的这个数的最大值,以及有多少种排列可以得到这个值。

$n\le 1000$ ,$x\le 5000$ 。


题解

组合数学+dp

由于 $a\ \text{mod}\ b<b$ ,因此每次产生影响(即 $x\ \text{mod}\ a_i\ne x$)的 $a_i$ 一定是递减的。

考虑将所有数从大到小排序处理。当确定了某个要产生影响的模数 $a_i$ ,$(x\ \text{mod}\ a_i,x]$ 中除了 $a_i$ 的数就都可以随便放在 $a_i$ 的后面,因为它们不会产生贡献。

设 $f[i]$ 表示处理完 $(i,+\infty)$ 的数,剩下的数为 $i$ 的方案数。

那么考虑 $f[i]$ ,枚举下一个选择的数 $j$ ,令 $s[i]$ 表示小于等于 $i$ 的数的个数,则有 $f[i\ \text{mod}\ j]=f[i]\times A_{s[i]-1}^{s[i]-1-s[i\ \text{mod}\ j]}=f[i]\times\frac{(s[i]-1)!}{(s[i\ \text{mod}\ j])!}$ 。预处理阶乘及阶乘的逆元即可。

时间复杂度 $O(n^2)$ 。

#include <cstdio>
#include <algorithm>
#define N 1010
#define M 5010
#define mod 998244353
using namespace std;
typedef long long ll;
int a[N] , sum[M];
ll fac[N] , inv[N] , fin[N] , f[M];
int main()
{
int n , m = 5000 , x , i , j , mn = m;
scanf("%d%d" , &n , &x);
for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]) , sum[a[i]] ++ , mn = min(mn , a[i]);
for(i = 1 ; i <= m ; i ++ ) sum[i] += sum[i - 1];
fac[0] = fin[0] = fac[1] = inv[1] = fin[1] = 1;
for(i = 2 ; i <= n ; i ++ )
{
fac[i] = fac[i - 1] * i % mod;
inv[i] = (mod - mod / i) * inv[mod % i] % mod;
fin[i] = fin[i - 1] * inv[i] % mod;
}
f[x] = fac[n] * fin[sum[x]] % mod;
for(i = m ; i ; i -- )
for(j = 1 ; j <= n ; j ++ )
if(a[j] <= i)
f[i % a[j]] = (f[i % a[j]] + f[i] * fac[sum[i] - 1] % mod * fin[sum[i % a[j]]]) % mod;
for(i = mn - 1 ; ~i ; i -- )
if(f[i])
break;
printf("%d %lld" , i , f[i]);
return 0;
}

【uoj#22】[UR #1]外星人 组合数学+dp的更多相关文章

  1. UOJ #22 UR #1 外星人

    LINK:#22. UR #1 外星人 给出n个正整数数 一个初值x x要逐个对这些数字取模 问怎样排列使得最终结果最大 使结果最大的方案数又多少种? n<=1000,x<=5000. 考 ...

  2. 【UOJ#22】【UR #1】外星人(动态规划)

    [UOJ#22][UR #1]外星人(动态规划) 题面 UOJ 题解 一道简单题? 不难发现只有按照从大往小排序的顺序选择的才有意义,否则先选择一个小数再去模一个大数是没有意义的. 设\(f[i][j ...

  3. Uoj 22 外星人

    Uoj 22 外星人 注意到一个数只有 \(\%\) 了小于等于自己的数时,才可能有变化,否则可以随意安排,不会对最后最优解造成影响. 用 \(f[x]\) 表示给一个数 \(x\) ,仅用 \(a[ ...

  4. 【bzoj1925】[Sdoi2010]地精部落 组合数学+dp

    题目描述 传说很久以前,大地上居住着一种神秘的生物:地精. 地精喜欢住在连绵不绝的山脉中.具体地说,一座长度为 N 的山脉 H可分 为从左到右的 N 段,每段有一个独一无二的高度 Hi,其中Hi是1到 ...

  5. 【UOJ#22】【UR#1】外星人

    2044年,Picks建成了人类第一台基于量子理论的银河系信息传递机. Picks游遍了宇宙,雇用了 n 个外星人来帮他作为信息传递机的中转站.我们将外星人依次编号为 1 到 n,其中 i 号外星人有 ...

  6. UOJ#22. 【UR #1】外星人

    传送门 分析 我们发现一个很神的性质,就是对于一个数如果放在它之前的数小于它那它一定对答案没有贡献 于是我们用dp[i][j]表示从大往小考虑了前i个数,当前答案是j的方案数 我们知道它由两种情况转移 ...

  7. UOJ22. 【UR #1】外星人【DP】【思维】

    LINK 题目大意 给你一个序列和一个值x 问你用某种方式对序列安排顺序之后一次对x取mod膜的最大值和方案数 首先发现一个性质 一个数之后所有比它大的数都没有贡献 考虑怎么利用这个性质? 就可以从小 ...

  8. UOJ #348 州区划分 —— 状压DP+子集卷积

    题目:http://uoj.ac/problem/348 一开始可以 3^n 子集DP,枚举一种状态的最后一个集合是什么来转移: 设 \( f[s] \) 表示 \( s \) 集合内的点都划分好了, ...

  9. Codeforces 722E 组合数学 DP

    题意:有一个n * m的棋盘,你初始在点(1, 1),你需要去点(n, m).你初始有s分,在这个棋盘上有k个点,经过一次这个点分数就会变为s / 2(向上取整),问从起点到终点的分数的数学期望是多少 ...

随机推荐

  1. 课下测试CH01补交

    课下测试CH01补交 ( 单选题 | 1 分) Amdahl定律说明,我们对系统的某个部分做出重大改进,可以显著获得一个系统的加速比. A . 正确 B . 错误 正确答案: B 你的答案: 未作答 ...

  2. 20155331 2016-2017-2 《Java程序设计》第10周学习总结

    20155331 2016-2017-2 <Java程序设计>第10周学习总结 教材学习内容总结 网络编程 网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据.程序员所作的事情就 ...

  3. 20155331 《Java程序设计》实验一(Java开发环境的熟悉)实验报告

    20155331 <Java程序设计>实验一(Java开发环境的熟悉)实验报告 一.实验内容及步骤 使用JDK编译.运行简单的java程序 实验目的与要求: 使用JDK和IDE编译.运行简 ...

  4. MySql访客连接设置

    步骤: 1 . 打开命令窗口,切换到mysql安装目录 可以在控制台目录切换,也可以打开所在安装目录后再打开控制台 2 . 执行命令:mysql -u root -p 3 . 无法访问的话,查看防火墙 ...

  5. springboot 中controller 返回html界面或 jsp界面

    参考链接:https://blog.csdn.net/qq_15260315/article/details/80907056 经尝试,返回html界面没问题,但是返回jsp界面是有问题的,just ...

  6. datax源代码编译安装

    what is DataX ? DataX是阿里巴巴集团内被广泛使用的离线数据同步工具/平台. 实现包括MySQL,SQL Server,Oracle,PostgreSQL,HDFS,Hive,HBa ...

  7. Maven学习(七)-----Maven添加远程仓库

    Maven添加远程仓库 默认情况下,Maven从Maven中央仓库下载所有依赖关系.但是,有些库丢失在中央存储库,只有在Java.net或JBoss的储存库远程仓库中能找到. 1. Java.net资 ...

  8. [Ubuntu] <uptime>命令

    uptime 命令 就是查看系统启动时间的,前几个大家应该都很熟悉:当前时间.系统启动时间.正在登陆的用户数 最后的三个数字,分别代表过去 1分钟  5分钟  15分钟  的平均负载(Load Ave ...

  9. K-近邻算法入门

    K-近邻算法的直观理解就是:给定一个训练集合,对于新的实例,在训练集合中找到k个与该实例最近的邻居,然后根据“少数服从多数”原则判断该实例归属于哪一类,又称“随大流” K-近邻算法的三大要素:K值得选 ...

  10. eclipse技巧-快捷键

    ctrl + 1,快速修复 ctrl + d, 快捷删除行 shift + Enter,快速移动光标到下一行 ctrl + F11,运行代码 alt + ↑/↓,快速移动行 ctrl + alt + ...