zoukankan      html  css  js  c++  java
  • CF1443E

    //CF1443 E
    /*
     算法:康托展开
     给定一个全排列,求它是第几小的全排列。
     如 4 2 1 3。
     解:
     int k=0;
     对于 4 它后面有三个数比他小:  k+=3 * (3!)     比它小的个数 * 排列数目,因为若前面的数保持不懂,仅仅统计当前数和它后面的数,1***,2***,3***均比它小共3 * (3!)种排列
     对于 2 它后面有一个数比他小:  k+=1 * (2!)     比它小的个数 * 排列数目,因为若前面的数保持不懂,仅仅统计当前数和它后面的数,41**          均比它小共1 * (2!)种排列
     对于 1 它后面有零个数比他小:  k+=0 * (1!)
     故答案为 20.
     求长度为n的第k小的全排列的多少?
     例:长度为4 第17小的全排列个数
     对于第一个数, 17/(3!)=2;故有1个数比第一个数小,第一个数为3
     17--> 5;
     对于第二个数, 5/(2!)=2;故有2个数比第二个数小,第一个数为4
     5-->1 ;
     对于第三个数, 1/(1!)=0;故有1个数比第三个数小,第一个数为2
     1-->0;
     答案为3 4 2 1
     对于本题,全排列的增量不会超过2e10;那么排列的变化范围不会超过后15个数.那么我只需要对后15个数进行处理
     技巧:若n不足15令n+=15
     */
    #include <bits/stdc++.h>
    #define inf 2333333333333333
    #define p(a) putchar(a)
    #define For(i,a,b) for(long long i=a;i<=b;++i)
    using namespace std;
    const long long maxn=2e5+100;
    void in(long long &x){
        long long y=1;char c=getchar();x=0;
        while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
        while(c<='9'&&c>='0'){ x=(x<<1)+(x<<3)+c-'0';c=getchar();}
        x*=y;
    }
    void o(long long x){
        if(x<0){p('-');x=-x;}
        if(x>9)o(x/10);
        p(x%10+'0');
    }
    long long n,q;
    long long base[30];
    long long a[maxn],sum[maxn];
    long long nowk=0;
    void init(){
        for(long long i=1;i<=18;i++)base[i]=1;
        for(long long i=1;i<=18;i++){
            for(long long j=1;j<=i;j++)base[i]*=j;
        }
        base[0]=1;
    }
    void push(long long x){
        nowk+=x;
        vector<long long>num;
        for(long long i=1;i<=15;i++){
            num.push_back(i);
        }
        long long head=n-15;
        long long nowkk=nowk;
        for(long long i=1;i<=15;i++){
            long long j=nowkk/base[15-i];
            nowkk-=j*base[15-i];
            a[head+i]=num[j]+n-15;
            sum[head+i]=sum[head+i-1]+a[head+i];
            num.erase(num.begin()+j,num.begin()+j+1);
        }
    }
    signed main(){
        init();
        long long op,x,y;
        in(n);in(q);
        long long del=0,up=0;
        for(long long i=1;i<=n+15;i++){
            a[i]=i;
            sum[i]=sum[i-1]+a[i];
        }
        if(n<15){
            del=15;
            up=15;
            n+=15;
        }
        while(q--){
            in(op);
            if(op==1){
                in(x),in(y);
                o(sum[y+up]-sum[x-1+up]-(y-x+1)*del);putchar('
    ');
            }
            if(op==2){
                in(x);
                push(x);
            }
    
        }
    
        return 0;
    }
    
  • 相关阅读:
    Core Data
    scrollViews
    网络通信
    UIView
    textView取消键盘
    AFNetworking转载
    多线程
    css3[转载][菜单导航] 带有记忆功能的多页面跳转导航菜单
    jQuery翻牌或百叶窗效果
    jQuery联动日历(三)完成
  • 原文地址:https://www.cnblogs.com/yesuweiYYYY/p/13933355.html
Copyright © 2011-2022 走看看