ligh1060(求字符串第k大排列)组合数学

题意:求给定字符串(有重复字符)第k大排列。

解法:先判断字符串的所有排列是否够k个。然后从左向右每一位每一位确定。简单的组合数学。

代码:

/****************************************************
* author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>

using namespace std;

#define eps 1e-8
typedef long long LL;

char s[30];
int per;
int len=0;
LL fac[21];
struct point
{
    char c;
    int x;
} points[100];
int tot=0;
void init()
{
    fac[0]=1;
    for(LL i=1; i<=20; i++)
        fac[i]=fac[i-1]*i;
}
LL cal()
{
    LL tool=1;
    int t=0;
    for(int i=0; i<=tot; i++)
        t+=points[i].x,tool*=fac[points[i].x];
    return fac[t]/tool;
}
void solve()
{
    if(cal()<per)
    {
        printf("Impossible\n");
        return ;
    }
    for(int i=0; i<len; i++)
    {
        LL tool=0;
        int j;
        for(j=0;j<=tot;j++)
        {
            points[j].x--;
            LL now=cal();
            tool+=now;
            if(tool>=per)
            {
                putchar(points[j].c);
                per-=tool-now;
                break;
            }
            points[j].x++;
        }
        if(points[j].x==0)
        {
            for(int k=j; k<tot; k++)
                points[k]=points[k+1];
            tot--;
        }
    }
    puts("");
}
int main()
{
    int t;
    cin>>t;
    int kk=1;
    init();
    while(t--)
    {
        tot=0;
        scanf("%s%d",s,&per);
        len=strlen(s);
        sort(s,s+len);
        points[tot].c=s[0];
        points[tot].x=1;
        for(int i=1; i<len; i++)
        {
            if(s[i]==s[i-1])
                points[tot].x++;
            else
            {
                points[++tot].c=s[i];
                points[tot].x=1;
            }
        }
        printf("Case %d: ",kk++);
        solve();
    }
    return 0;
}

ligh1060(求字符串第k大排列)组合数学

时间: 2024-10-21 11:30:45

ligh1060(求字符串第k大排列)组合数学的相关文章

UVA - 12335 Lexicographic Order (第k大排列)

Description A Lexicographic Order Input: Standard Input Output: Standard Output The alphabet of a certain alien language consists of n distinct symbols. The symbols are like the letters of English alphabet but their ordering is different. You want to

poj2104 求区间第k大 可持久化线段树

poj2104 求区间第k大  可持久化线段树 #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef

POJ2761---Feed the dogs (Treap求区间第k大)

题意 就是求区间第k大,区间 不互相包含. 尝试用treap解决一下 第k大的问题. 1 #include <set> 2 #include <map> 3 #include <cmath> 4 #include <ctime> 5 #include <queue> 6 #include <stack> 7 #include <cstdio> 8 #include <string> 9 #include <

poj 2401 划分树 求区间第k大的数

题目:http://poj.org/problem?id=2104 划分树待我好好理解下再写个教程吧,觉得网上的内容一般,,, 模板题: 贴代码: #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define CLR(a) memset(a,0,sizeof(a)) const int MAXN = 1000

hdu 2665 可持久化线段树求区间第K大值(函数式线段树||主席树)

http://acm.hdu.edu.cn/showproblem.php?pid=2665 Problem Description Give you a sequence and ask you the kth big number of a inteval. Input The first line is the number of the test cases. For each test case, the first line contain two integer n and m (

POJ 2761 Feed the dogs(树状数组求区间第K大)

题目链接: 戳我 题目大意:Jiajia要为宠物狗,宠物狗按成一排站好(1 < i <= n),第 i 只狗的喜欢程度是 a[i], 之后他会先喂某个区间内第k个 即 n 个数, m个询问,接着是 n个数 接下来 m 行,每行是 l r k即 l 到 r 这个区间第 k 小的数,每个询问输出一个答案,即 a[i] 求区间第k大有很多算法, 详见此博客 [数据结构练习] 求区间第K大数的几种方法 我用的树状数组解法,来自 树状数组从前往后求和,用来解第k大(或小)的数 poj 2985 The

求区间第k大的值

#include <iostream> using namespace std; int part(int a[], int i, int j) { int tmp = a[i]; if(i < j) { while(i < j) { while(i<j && a[j]>=tmp) j--; if(i < j) a[i] = a[j]; while(i<j && a[i]<tmp) i++; if(i < j) a

POJ 1442 Black Box treap求区间第k大

题目来源:POJ 1442 Black Box 题意:输入xi 输出前xi个数的第i大的数 思路:试了下自己的treap模版 #include <cstdio> #include <cstring> #include <cstdlib> #include <ctime> using namespace std; struct Node { Node *ch[2]; int r; int v; int s; Node(){} Node(int v): v(v)

zoj 2112 块状链表求动态第k大

块内排序方便二分,然后进行类似于冒泡排序的更新即可. 1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 #include <cmath> 6 using namespace std; 7 8 const int INF = 1000000000; 9 const int N = 50000; 10 const int M