题目链接:http://acm.swust.edu.cn/problem/715/

Time limit(ms): 1000      Memory limit(kb): 65535
 
在数据加密和数据压缩中常需要对特殊的字符串进行编码。给定的字母表A 由26 个小写英文字母组成A={a,b,…,z}。该字母表产生的升序字符串是指字符串中字母按照从左到右出现的次序与字母在字母表中出现的次序相同,且每个字符最多出现1 次。例如,a,b,ab,bc,xyz 等字符串都是升序字符串。现在对字母表A 产生的所有长度不超过6 的升序字符串按照字典序排列并编码如下。

1 2 … 26 27 28 …
a b … z ab ac …

对于给定的长度不超过6 的升序字符串,编程计算出它在上述字典中的编码。

Description
文件的第一行是一个正整数k,表示接下来共有k 行。 
接下来的k行中,每行给出一个字符串。

Input
共有k 行,每行对应于一个字符串的编码。

Output
1
2
3
2
a
b
Sample Input
1
2
1
2
Sample Output
 
 
解题思路:这道题用数位dp的话不太现实(状态设计太诡异的说~~~)
     那么指定个  字母   只有一个排列合法,符合组合数的概念,可以考虑使用组合数
     然后在当前状态下,求长度小于len的总个数,等于len的当前序列的总个数(相当于把问题细化了)
     具体的看代码吧~~~
 
    值得注意的是   利用杨辉三角计算组合数   且合数性质cur[i][j]=cur[i][i-j];
 
代码如下:
 #include <iostream>
#include <cstring>
using namespace std; char s[];
int cur[][] = { }; //预处理 利用杨辉三角计算组合数
void init(){
int i, left, right;
for (i = ; i <= ; i++){
cur[i][] = cur[i][i] = ;
left = , right = i - ;
while (left <= right){
cur[i][left] = cur[i - ][left - ] + cur[i - ][left];
cur[i][right--] = cur[i][left++];//组合数性质cur[i][j]=cur[i][i-j];
}
}
} //长度小于len的串的个数
int minlen_num(int len){
int i, cnt = ;
for (i = ; i < len; i++)
cnt += cur[][i];
return cnt;
} //当前长度下当前串前面的个数
int enquallen_num(int len){
int i, j, cnt = , pre = -, tmp;
for (i = ; i < len; i++){
tmp = s[i] - 'a';
for (j = pre + ; j < tmp; j++)
cnt += cur[ - j - ][len - i - ];
pre = tmp;
}
return cnt;
} bool judge(int len){
for (int i = ; i < len; i++)
if (s[i] <= s[i - ])
return false;
return true;
} int main(){
init();
int t, cnt, len;
cin >> t;
while (t--){
cnt = ;
cin >> s;
len = strlen(s);
if (!judge(len)) cout << << endl;
else{
cnt += minlen_num(len);
cnt += enquallen_num(len);
cout << cnt + << endl;
}
}
return ;
}

6/18号我又回来了,这道题是可以数位dp的,当时我设计状态的时候果断逗比了~~~直接在递归时,加个判断就限制了后面数字的选取状态就可以强势ac了

(感谢学长的指点)

代码如下:

 #include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define ll long long
#define N 110 char s[N];
ll bit[N];
ll dp[N][N]; ll dfs(ll pos, ll mx, bool limit, bool fzero)
{
if (pos == -) return ;
if (!limit && !fzero && ~dp[pos][mx]) return dp[pos][mx];
ll end = limit ? bit[pos] : ;
ll ans = ;
for (ll i = fzero ? : mx; i <= end; i++)//这里就判断了后面的字母的选取是否有限制(题目上的升序)
{
ans += dfs(pos - , i + , limit && i == end, fzero && !i);
}
if (!limit && !fzero) dp[pos][mx] = ans;
return ans;
}
ll cal()
{
ll len = strlen(s + );
for (ll i = ; i <= len; i++)
{
bit[len - i] = s[i] - 'a' + ;
}
return dfs(len - , , , );
}
int main()
{
int t;
cin >> t;
while (t--)
{
memset(dp, -, sizeof(dp));
scanf("%s", s + );
int flag = ;
int len = strlen(s + );
for (int i = ; i<len; i++)
{
if (!(s[i]<s[i + ]))
{
flag = ;
break;
}
}
if (!flag) printf("0\n");
else
printf("%lld\n", cal() - );
}
return ;
}

[Swust OJ 715]--字典序问题(组合数预处理/数位dp)的更多相关文章

  1. [UOJ86]mx的组合数——NTT+数位DP+原根与指标+卢卡斯定理

    题目链接: [UOJ86]mx的组合数 题目大意:给出四个数$p,n,l,r$,对于$\forall 0\le a\le p-1$,求$l\le x\le r,C_{x}^{n}\%p=a$的$x$的 ...

  2. Light OJ 1032 - Fast Bit Calculations(数位DP)

    题目大意: 一个数字把他看成二进制数字,数字里又会一些相邻的1,问从0到n至间所有相邻1的总和是多少?   分解成2进制数字,然后数位DP就行了.   ======================== ...

  3. UOJ#275. 【清华集训2016】组合数问题 数位dp

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ275.html 题解 用卢卡斯定理转化成一个 k 进制意义下的数位 dp 即可. 算答案的时候补集转化一下 ...

  4. [Swust OJ 247]--皇帝的新衣(组合数+Lucas定理)

    题目链接:http://acm.swust.edu.cn/problem/0247/ Time limit(ms): 1000 Memory limit(kb): 65535   Descriptio ...

  5. [Swust OJ 581]--彩色的石子(状压dp)

    题目链接:http://acm.swust.edu.cn/problem/0581/ Time limit(ms): 1000 Memory limit(kb): 65535   Descriptio ...

  6. swust oj 2516 教练我想学算术 dp+组合计数

    #include<stdio.h> #include<string.h> #include<iostream> #include<string> #in ...

  7. BZOJ 3209 花神的数论题 数位DP+数论

    题目大意:令Sum(i)为i在二进制下1的个数 求∏(1<=i<=n)Sum(i) 一道非常easy的数位DP 首先我们打表打出组合数 然后利用数位DP统计出二进制下1的个数为x的数的数量 ...

  8. [Swust OJ 541]--排列字典序问题

    题目链接:http://acm.swust.edu.cn/problem/0541/ Time limit(ms): 2000 Memory limit(kb): 65535 n个元素{1,2,... ...

  9. [Swust OJ 1097]--2014(数位dp)

    题目链接:http://acm.swust.edu.cn/problem/1097/ Time limit(ms): 1000 Memory limit(kb): 32768   今年是2014年,所 ...

随机推荐

  1. bzoj 2763: [JLOI2011]飞行路线 分层图

    题目链接 n个点m条路, 每条路有权值,  给出起点和终点, 求一条路使得权值最小.可以使路过的路中, k条路的权值忽略. 其实就是多一维, 具体看代码 #include<bits/stdc++ ...

  2. android--email发送邮件,文本还有附件形式的邮件

    1.首先用的jar包为javaemail 下载地址: https://yunpan.cn/cB3kY8WIvcGtU (提取码:e042) 2.工具包 package com.kllayhello.u ...

  3. js函数调用模式总结

    在javascript中一共有四种调用模式:方法调用模式.函数调用模式.构造器调用模式和apply调用模式.这些模式在如何初始化关键参数this上存在差异 方法调用模式 当一个函数被保存为对象的一个属 ...

  4. 表格java代码的相关知识积累

    本文主要收集各大博客中的java表格 用JSP创建一个表格模板 . 项目中要用到一些展示信息的表格,表头不固定,表格内容是即时从后台取的:考虑到复用性,笔者用jsp编写了一个表格模板,可以从reque ...

  5. 从一个App跳转到另一个App

    在跳入App的info中配置Bundle identifier 在跳入App的info中配置URL Schemes 在另一个应用程序中按照上边的操作添加openURL并运行,就可以跳转了 调用open ...

  6. lua协程并发下载简单测试

    下载8个1m大小文件,测试五次分别耗时12.038s,10.316s,8.955s,11.275s,9.499s(lua代码实现如下) require "socket" --hos ...

  7. c 输入两个数,第一个数决定一个nXn的矩阵,第二个数决定从1开始赋值,赋值的上限 (MD花了半天时间,思路不对害死人)

    输入两个数,第一个数决定一个nXn的矩阵,第二个数决定从1开始赋值,赋值的上限 比如: 输入: 输出: 输入: 输出: #include<stdio.h> int main(void) { ...

  8. 利用GDataXML解析XML文件

    1.导入GDataXMLNode.h 和 GDataXMLNode.m文件 2.导入libxml2库文件 3.工程target下Bulid Settings  搜索search 找到Hearder S ...

  9. java concurrency: ThreadLocal及其实现机制

    转载:http://shmilyaw-hotmail-com.iteye.com/blog/1703382 ThreadLocal概念 从字面上来理解ThreadLocal,感觉就是相当于线程本地的. ...

  10. C - N皇后问题(搜索)

    Description 在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上. 你的任务是,对于给定的N,求出有多少种合 ...