zoukankan      html  css  js  c++  java
  • CF1326C Permutation Partitions 题解

    CSDN同步

    原题链接

    简要题意:

    给定一个 (1) ~ (n) 的置换,将数组分为 (k) 个区间,使得每个区间的最大值之和最大。求这个值,和分区的方案数。

    关键在于 (1) ~ (n) 的置换。

    显然,你只要把从 (n - k + 1)(n) 这一段,每个区间分一个(其余的随便分)。

    显然可以得出第一个答案:

    [(n-k+1) + (n-k+1) + cdots + (n-1) + n ]

    (很显然,你可以用等差数列求和,可是没这个必要,一会儿求第二个答案的时候,可以顺便求啊

    比方说:(以第三个样例为例)

    7 3
    2 7 3 1 5 4 6
    

    这时你把 (5)(6)(7) 作为每个区间的最大值。

    此时你会发现,比方说 (3 space 1) 这一段。

    它要么全归 (7),全归 (5) ,或者分两段,左边归 (7),右边归 (5).

    那么,你想,这就相当于你可以在任意的位置把它分段。(包括最左边和最右边,此时尽属一段)

    那么,方案数是 (3).

    就是 (5) 的位置减去 (7) 的位置,即 (5 - 2 = 3).

    而一共三段,分别计算。根据 乘法原理 可得:

    [1 imes 3 imes 2 = 6 ]

    所以,第二个答案是:

    每个 (geq n - k + 1) 的数和前面一个 (geq n - k + 1) 的数的位置之差的乘积。

    第零个 (geq n - k + 1) 的数的位置,我们认为是 (0).

    记得开 ( exttt{long long}).

    十年OI一场空,不开long long见祖宗

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const ll MOD=998244353;
    
    inline int read(){char ch=getchar();int f=1;while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
    	int x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}
    
    int n,k,last;
    ll s=0,cnt=1;
    
    int main(){
    	n=read(),k=read();
    	for(int i=1,t;i<=n;i++) {
    		t=read(); if(t>n-k) {
    			s+=t; if(!last) last=i; //维护上一个 >= n - k + 1 的数的位置
    			else cnt=cnt*(i-last)%MOD,last=i; //计数
    		} 
    	} printf("%lld %lld
    ",s,cnt); 
    	return 0;
    }
    
    
  • 相关阅读:
    mysql中给查询结果添加序号
    Mysql如何取当日的数据
    nginx 出现413 Request Entity Too Large问题的解决方法
    Mac 安装Jupyter Notebook
    Python-用xlrd模块读取excel,数字都是浮点型,日期格式是数字的解决办法
    sql-exists、not exists的用法
    sql语句replace函数的使用
    Python-日期格式化
    Python-自动用0补取长度
    Flask-实现下载功能
  • 原文地址:https://www.cnblogs.com/bifanwen/p/12545373.html
Copyright © 2011-2022 走看看