Uoj 22 外星人

Uoj 22 外星人

  • 注意到一个数只有 \(\%\) 了小于等于自己的数时,才可能有变化,否则可以随意安排,不会对最后最优解造成影响.
  • 用 \(f[x]\) 表示给一个数 \(x\) ,仅用 \(a[i]<=x\) 的 \(a[i]\) 时,得到的最大数.用 \(g[x]?\) 表示最优情况下的方案数目.
  • 转移时,对于会造成影响的数,我们枚举第一个位置填的数,对于不会造成影响的数,就任意给它们钦定位置.
  • 记 \(p=x\ mod\ a[i]\) ,\(count_k\) 表示小于等于 \(k\) 的 \(a[i]?\) 个数,容易写出转移方程:

\[
f[x]=\max_{a[i] \leq x} (f[x],f[p])\g[x]=\sum_{a[i]\leq x\ ,\ f[p]=f[x]}g[p]*A(count_x-1,count_p-1)
\]

  • 边界条件:

\[
f[x]=x,count_x=0\g[x]=1,count_x=0
\]

  • 最后输出答案的时候还要注意大于给出 \(x\) 的数可以任意放.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read()
{
    int out=0,fh=1;
    char jp=getchar();
    while ((jp>'9'||jp<'0')&&jp!='-')
        jp=getchar();
    if (jp=='-')
        fh=-1,jp=getchar();
    while (jp>='0'&&jp<='9')
        out=out*10+jp-'0',jp=getchar();
    return out*fh;
}
const int P=998244353;
inline int add(int a,int b)
{
    return (a + b) % P;
}
inline int mul(int a,int b)
{
    return 1LL * a * b % P;
}
int fpow(int a,int b)
{
    int res=1;
    while(b)
        {
            if(b&1)
                res=mul(res,a);
            a=mul(a,a);
            b>>=1;
        }
    return res;
}
const int MAXN=1e3+10,MAXV=5e3+10;
int n,X;
int a[MAXN],f[MAXV],g[MAXV];
int fac[MAXV],invfac[MAXV];
void init()
{
    int lim=5000;
    fac[0]=1;
    for(int i=1;i<=lim;++i)
        fac[i]=mul(fac[i-1],i);
    invfac[lim]=fpow(fac[lim],P-2);
    for(int i=lim-1;i>=0;--i)
        invfac[i]=mul(invfac[i+1],i+1);
}
int A(int n,int m)
{
    if(m<0 || n<0 || m>n)
        return 0;
    return mul(fac[n],invfac[n-m]);
}
int count(int L,int R)//计算a数组从L到R有多少个数
{
    if(L>R)
        return 0;
    int l=lower_bound(a+1,a+1+n,L)-a;
    int r=upper_bound(a+1,a+1+n,R)-a-1;
    return r-l+1;
}
int dfs(int x)
{
    if(f[x]!=-1)
        return f[x];
    f[x]=-1,g[x]=0;
    int k=count(1,x);
    if(k==0)
        {
            f[x]=x;
            g[x]=1;
            return x;
        }
    for(int i=1;i<=n;++i)
        {
            if(a[i]<=x)
                {
                    int p=x%a[i];
                    f[x]=max(f[x],dfs(p));
                }
            else
                break;
        }
    for(int i=1;i<=n;++i)
        {
            if(a[i]>x)
                break;
            int p=x%a[i];
            if(f[p]!=f[x])
                continue;
            int tmp=g[p];
            int tot=count(1,x)-1,par=count(p+1,x)-1;
            tmp=mul(tmp,A(tot,par));
            g[x]=add(g[x],tmp);
        }
    return f[x];
}
int main()
{
    init();
    n=read(),X=read();
    memset(f,-1,sizeof f);
    for(int i=1;i<=n;++i)
        a[i]=read();
    sort(a+1,a+1+n);
    dfs(X);
    int t=count(X+1,a[n]);
    printf("%d\n%d\n",f[X],mul(g[X],A(n,t)));
    return 0;
}

原文地址:https://www.cnblogs.com/jklover/p/10470324.html

时间: 2024-08-29 22:18:06

Uoj 22 外星人的相关文章

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

[UOJ#22][UR #1]外星人(动态规划) 题面 UOJ 题解 一道简单题? 不难发现只有按照从大往小排序的顺序选择的才有意义,否则先选择一个小数再去模一个大数是没有意义的. 设\(f[i][j]\)表示考虑了前\(i\)个数,模完之后是\(j\)的方案数. 转移的时候枚举这个数是模还是不模,如果不模的话就要把它放到后面某个小数的后面,方案数是\(n-i\). #include<iostream> #include<cstdio> #include<cstdlib>

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

2044年,Picks建成了人类第一台基于量子理论的银河系信息传递机. Picks游遍了宇宙,雇用了 n 个外星人来帮他作为信息传递机的中转站.我们将外星人依次编号为 1 到 n,其中 i 号外星人有 ai 根手指. 外星人都是很低级的,于是Picks花费了很大的精力,才教会他们学会扳手指数数. Picks现在准备传递 x 个脉冲信号给VFleaKing,于是他把信号发给1号外星人,然后1号外星人把信号发送给2号外星人,2号外星人把信号发送给3号外星人,依次类推,最后n号外星人把信号发给VFle

UOJ 外星人

题目: 2044年,Picks建成了人类第一台基于量子理论的银河系信息传递机.Picks游遍了宇宙,雇用了n个外星人来帮他作为信息传递机的中转站.我们将外星人依次编号为1 到n,其中i 号外星人有ai 根手指.外星人都是很低级的,于是Picks花费了很大的精力,才教会他们学会扳手指数数.Picks现在准备传递x 个脉冲信号给VFleaKing,于是他把信号发给1号外星人,然后1号外星人把信号发送给2号外星人,2号外星人把信号发送给3号外星人,依次类推,最后n号外星人把信号发给VFleaKing.

【UOJ Round #1】

枚举/DP+排列组合 缩进优化 QAQ我当时一直在想:$min\{ \sum_{i=1}^n (\lfloor\frac{a[i]}{x}\rfloor + a[i] \ mod\ x) \}$ 然而并不会做啊……一点思路也没有……主要是后面那个取模非常难受…… 其实正解有点逆向思维的感觉:$ans=\sum_{i=1}^n a[i] - max\{ \sum_{i=1}^n \lfloor \frac{a[i]}{x}\rfloor *(x-1) \} $ 也就是先将a[i]全部加起来,然后再

【UOJ Round #3】

枚举/二分 C题太神窝看不懂…… 核聚变反应强度 QwQ很容易发现次小的公约数一定是gcd的一个约数,然后……我就傻逼地去每次算出a[1],a[i]的gcd,然后枚举约数……这复杂度……哦呵呵... 正解是先找到a[1]的所有质因数啊……然后在刚刚那个算法的“枚举gcd的约数”的时候直接枚举这些质因数就好了…… 1 //UOJ Round3 A 2 #include<vector> 3 #include<cstdio> 4 #include<cstring> 5 #in

【UOJ Round #8】

A 一道不错的题,虽然大家都觉得是水题,然而蒟蒻我想出来的好慢……Orz alpq 发现其实就是一个网格图,每一个大块都是同一颜色……横纵坐标互不干扰…… 1 //UOJ Round #8 A 2 #include<vector> 3 #include<cstdio> 4 #include<cstring> 5 #include<cstdlib> 6 #include<iostream> 7 #include<algorithm> 8

UOJ#179. 线性规划[模板]

传送门 http://uoj.ac/problem/179 震惊,博主竟然还不会线性规划! 单纯形实在学不会啊……背个板子当黑盒用…… 学(chao)了NanoApe dalao的板子 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 using namespace std; 7 const d

【NOIP2017模拟8.7】外星人的路径

Description 有一个外星人控制了你的大脑.一开始你处于原点(0,0).外星人有一个由(R,U,D,L)组成的长度为M 的操作序列,分别代表(右,上,下,左).平面上有N 个关键点,每当外星人给出一个操作,你需要在这个方向上找到最近的一个关键点,并走到那个点上.保证输入数据合法.上图为第三个样例的图示. Input 第一行两个整数N,M.接下来N 行,每行两个整数xi,yi,代表第i 个点的坐标.接下来一行,一个长度为M 的字符串,代表操作序列. Output 一行两个整数,代表最终你所

UOJ#21【UR #1】缩进优化

传送门 http://uoj.ac/problem/21 枚举 (调和级数?) $\sum_{i=1}^{n} (a_i / x + a_i \bmod x) =\sum a_i - (\sum_{i=1}^{n} a_i /x) * (x-1)$ 看上去并没有一个很好的办法确定x的取值? 大概只能暴力枚举了. 枚举x的大小,如果用分块加速的方法统计解,复杂度是O(n)+O(n/2)+O(n/3)+O(n/4)+... 累积起来是O(nlogn) 嗯?好像是正解? イミワカナイ 1 #inclu