zoukankan      html  css  js  c++  java
  • 2017 Multi-University Training Contest

    Limited Permutation

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6044

    题意:现在有一个排列p1,p2,p3,p4,p5,p6…………pn,然后再给你n对区间[Li,Ri]【i表示第i个区间】。现在有一个这样的定义min(pL,pL+1,,pR)=pi,也就是说对于第i个区间[Li,Ri]中最小的是一个pi,问这样的排列有多少个?

    思路:我们先分析题目意思从min(pL,pL+1,,pR)=pi中我们可以分析由于最终要确定这个排列所以必定存在一个区间是[1,n]这样才能确定最小的哪一位,假设这是第i组区间,就把整个[1,n]的区间分成两半,一个是[1,i-1].一个是[i+1,n],从而确定了最小的数1在第i个位置。对于两个子区间我们以[1,n-1]这个区间为例,我们是不是也需要一个区间刚好是[1,i-1]我们才能确定[1,i-1]这个区间内最小的那个值是哪一个。以此类推,又可以分成两个区间,右边的那个区间也是这样。所以我们可以的得到得到这样的一个结论,只要在这个分区间的过程中其中一个区间不存在,我就无法确定区间最小,也就无法形成一个区间,这个时候答案就是零。如果所有区间都存在着就是一个组合数的问题,我们思考对于[1,n]这个区间分成[1,i-1]和[i+1.n]两个区间对于左边区间是不是需要i-1个数,而总共是n-1个数,是不相当于乘以C(n-1,i-1)的组合数,然后进一步递归下去,链乘上分区间返回上来的组合数,还有右边返回上来的组合数这个具体看代码。

    对于判断这个区间是否存在一开始的dfs,然后用map去判断结果超时了,可能是由于组合数取膜使用的乘法逆元是用快速幂求出来的,据说可以n的复杂度预处理逆元,不太会……所以超时了。后来发现一个规律,我们可以一开始的时候对于一个区间用以左节点升续排序,左节点相同以右节点的降序排列,这样就实际上就是一个dfs序,我们仔细分析我们之前操作。实际上就是一个dfs的过程,如果排列存在,那么我们在dfs过程中遇到的区间应该严格与我们排完序的区间吻合,如果不吻合,就说明区间不存在,可能不太好理解。自己模拟一遍这个dfs的过程就会明白了。

    这道题还有一个究极输入挂:

    代码:

    const int MAXBUF = 10000;
    char buf[MAXBUF], *ps = buf, *pe = buf+1;
    
    inline void rnext()
    {
        if(++ps == pe)
            pe = (ps = buf)+fread(buf,sizeof(char),sizeof(buf)/sizeof(char),stdin);
    }
    
    template <class T>
    inline bool readin(T &ans)
    {
        ans = 0;
        T f = 1;
        if(ps == pe) return false;//EOF
        do{
            rnext();
            if('-' == *ps) f = -1;
        }while(!isdigit(*ps) && ps != pe);
        if(ps == pe) return false;//EOF
        do
        {
            ans = (ans<<1)+(ans<<3)+*ps-48;
            rnext();
        }while(isdigit(*ps) && ps != pe);
        ans *= f;
        return true;
    }

    由于数据量很大,所以需要这个超级输入挂,没有这个输入挂是过不了的,可以记下来。

    AC代码:

      1 //Author: xiaowuga
      2 #include <iostream>
      3 #include <algorithm>
      4 #include <set>
      5 #include <vector>
      6 #include <queue>
      7 #include <cmath>
      8 #include <cstring>
      9 #include <cstdio>
     10 #include <ctime>
     11 #include <map>
     12 #include <bitset>
     13 #include <cctype>
     14 #define maxx INT_MAX
     15 #define minn INT_MIN
     16 #define inf 0x3f3f3f3f
     17 #define mem(s,ch) memset(s,ch,sizeof(s))
     18 #define da cout<<da<<endl
     19 #define uoutput(a,i,l,r) for(int i=l;i<r;i++) if(i==l) cout<<a[i];else cout<<" "<<a[i];cout<<endl;
     20 #define doutput(a,i,l,r) for(int i=r-1;i>=0;i--) if(i==r-1) cout<<a[i];else cout<<" "<<a[i];cout<<endl;
     21 const long long N= 1000000+10;
     22 const long long mod=1e9+7;
     23 using namespace std;
     24 typedef long long LL;
     25 LL mi[N];
     26 LL n,flag,ct;
     27 struct node{
     28     LL x,y,z;
     29     bool operator <(const node &m) const{
     30         if(x==m.x) return y>=m.y;
     31         else return x<m.x;
     32     }
     33 }oj[N];
     34 LL q_power(LL a,LL k){
     35     LL ans=1;
     36     while(k){
     37         if(k%2) ans=ans*a%mod;
     38         k/=2;
     39         a=a*a%mod;
     40     }
     41     return ans;
     42 }
     43 void init(){
     44     mi[1]=mi[0]=1;
     45     for(int i=2;i<=N-1;i++){
     46         mi[i]=mi[i-1]*i%mod;
     47     }
     48 }
     49 
     50 LL cal(LL a,LL b){
     51      LL ans=1;
     52      ans=mi[a]*q_power(mi[a-b],mod-2)%mod;
     53      ans=ans*q_power(mi[b],mod-2)%mod;
     54      
     55      return ans;
     56 }
     57 LL dfs(LL x,LL y){
     58     if(flag) return 0;
     59     if(x>y) return 1;
     60     if(oj[ct].x!=x||oj[ct].y!=y){
     61         flag=1;return 0;
     62     }
     63     node t=oj[ct];
     64     ct++;
     65     if(x==y) return 1;
     66     LL res=cal(t.y-t.x,t.z-t.x)*dfs(t.x,t.z-1)%mod;
     67     res=res*dfs(t.z+1,t.y)%mod;
     68     return res;
     69 }
     70 
     71 const int MAXBUF = 10000;
     72 char buf[MAXBUF], *ps = buf, *pe = buf+1;
     73 
     74 inline void rnext()
     75 {
     76     if(++ps == pe)
     77         pe = (ps = buf)+fread(buf,sizeof(char),sizeof(buf)/sizeof(char),stdin);
     78 }
     79 
     80 template <class T>
     81 inline bool readin(T &ans)
     82 {
     83     ans = 0;
     84     T f = 1;
     85     if(ps == pe) return false;//EOF
     86     do{
     87         rnext();
     88         if('-' == *ps) f = -1;
     89     }while(!isdigit(*ps) && ps != pe);
     90     if(ps == pe) return false;//EOF
     91     do
     92     {
     93         ans = (ans<<1)+(ans<<3)+*ps-48;
     94         rnext();
     95     }while(isdigit(*ps) && ps != pe);
     96     ans *= f;
     97     return true;
     98 }
     99 int main() {
    100     //freopen("data.txt","r",stdin);
    101     init();
    102     int h=0;
    103     while(readin(n)){
    104         for(int i=1;i<=n;i++) readin(oj[i].x);
    105         for(int i=1;i<=n;i++) {
    106             readin(oj[i].y);
    107             oj[i].z=i;
    108         }
    109         flag=0;ct=1;
    110         sort(oj+1,oj+n+1);
    111         printf("Case #%d: %lld
    ",++h,dfs(1LL,n));
    112     }
    113     return 0;
    114 }
    View Code
  • 相关阅读:
    6.简单总结一下类与对象
    5.创建对象内存分析
    4.构造器详解
    3.类和对象的关系
    业余草推荐18个Java开源免费的CMS系统
    业余草教你解读Spark源码阅读之HistoryServer
    业余草公众号运营攻略:教你一天涨粉200以上
    从菜鸟到大牛的码农升职必学文章推荐
    倒排索引的AND操作
    程序员,如何在工作之外,增加自己的收入
  • 原文地址:https://www.cnblogs.com/xiaowuga/p/7260902.html
Copyright © 2011-2022 走看看