NAIPC2018

参考:http://www.cnblogs.com/LQLlulu/p/9513669.html?tdsourcetag=s_pctim_aiomsg

https://www.cnblogs.com/clrs97/p/8730429.html?tdsourcetag=s_pctim_aiomsg

E-Prefix Free Code

题目描述

Consider n initial strings of lower case letters, where no initial string is a prefix of any other initial string. Now, consider choosing k of the strings (no string more than once), and concatenating them together. You can make this many such composite strings:

n × (n − 1) × (n − 2) × . . . × (n − k + 1)

Consider sorting all of the composite strings you can get via this process in alphabetical order. You are given a test composite string, which is guaranteed to belong on this list. find the position of this test composite string in the alphabetized list of all composite strings, modulo 109 +7. The first composite string in the list is at position 1.

输入

Each input will consist of a single test case. Note that your program may be run multiple times on different inputs. Each test case will begin with a line with two integers, first n and then k(1 ≤ k ≤ n), where n is the number of initial strings, and k is the number of initial strings you choose to form composite strings. The upper bounds of n and k are limited by the constraints on the strings, in the following paragraphs.

Each of the next n lines will contain a string, which will consist of one or more lower case letters a..z. These are the n initial strings. It is guaranteed that none of the initial strings will be a prefix of any other of the initial strings.

finally, the last line will contain another string, consisting of only lower case letters a..z. This is the test composite string, the position of which in the sorted list you must find. This test composite string is guaranteed to be a concatenation of k unique initial strings.

The sum of the lengths of all input strings, including the test string, will not exceed 106 letters.

输出

Output a single integer, which is the position in the list of sorted composite strings where the test composite string occurs. Output this number modulo 109 + 7.

样例输入

5 3

a

b

c

d

e

cad

样例输出

26

一开始的思路:

用map把输入的字符串按字典序标记一个数字,因为涉及到排序和map 就要用string。然后再将要处理的字符串也化为数字,然后就是求这个排列是第几个,对于每位数字,减去前面有多少比它小的-1,然后乘以后面的全排列就好了。终于找前面有多少个比它小的,当然是暴力啦1e6/2=1e3最后半小时才意识到要用树状数组,然而还是内存超限。

正解:

怎么没想到字典树呢?好吧其实是想到的但是不会先建树,因为题中说没有单词是另一个单词的前缀,cnt[]维护每个单词的编号。然后再用一个num[]维护一下单词的字典次序,这个怎么维护呢?直接跑一遍tire,就可以了。num[cnt[u]]相当于之前方法的字符串转化为数字:正好复习一下tire模板

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e6+5;
const int mod=1e9+7;
int n,k,ant;
int s[maxn],c[maxn],cnt[maxn],num[maxn];
int tire[maxn][30];
ll f[1000010],invf[1000010];
char str[maxn];
ll qmul(ll a,ll b){ll ret=0; while(b){ if(b&1) ret=(ret+a)%mod; a=(a+a)%mod; b>>=1;} return ret;}
ll qpow(ll a,ll b){ll ret=1; while(b){ if(b&1) ret=qmul(ret,a); a=qmul(a,a); b>>=1;} return ret;}
void init(){
f[0]=1;
for(ll i=1;i<=1000001;i++) f[i]=f[i-1]*i%mod;
invf[1000001]=qpow(f[1000001],mod-2);
for(ll i=1000000;i>=0;i--) invf[i]=invf[i+1]*(i+1)%mod;
}
inline int lowbit(int x){return x&-x;}
inline void add(int x,int val){
for(int i=x;i<=n;i+=lowbit(i)){
c[i]+=val;
}
}
inline int getsum(int x){
int ret=0;
for(int i=x;i>0;i-=lowbit(i)){
ret+=c[i];
}
return ret;
}
void ins(char *str)
{
int len=strlen(str);
int p=0;
for(int i=0;i<len;i++){
int ch=str[i]-'a';
if(!tire[p][ch])
tire[p][ch]=++ant;
p=tire[p][ch];
}
cnt[p]++;
//cout<<p<<" "<<cnt[p]<<endl;
}
//int srh(char *str)
//{
// int ans=0;
// int len=strlen(str);
// int p=0;
// for(int i=0;i<len;i++){
// int ch=str[i]-'a';
// p=tire[p][ch];
// if(!p) return ans;
// ans+=cnt[p];
// }
// return ans;
//}
int op;
void cal(int u)
{ if(cnt[u]){
op++;
num[u]=op;
return;
}
for(int i=0;i<26;i++){
if(tire[u][i])
cal(tire[u][i]);
}
}
int main()
{
init();
ios::sync_with_stdio(false);
cin.tie(0);
while(cin>>n>>k){
ant=0;
memset(cnt,0,sizeof(cnt));
memset(tire,0,sizeof(tire));
memset(c,0,sizeof(c));
memset(num,0,sizeof(num));
for(int i=1;i<=n;i++){
cin>>str;
ins(str);
}
cin>>str;
op=0;
cal(0);
ll ans=0;
ll t;
int x;
int u=0,id=0;
int len=strlen(str);
for(int i=0;i<len;i++){
t=str[i]-'a';
u=tire[u][t];
if(cnt[u]){
id++;
x=getsum(num[u]);
ans=(ans+qmul(qmul((num[u]-1-x),f[n-id]),invf[n-k]))%mod;
add(num[u],1);
u=0;
}
}
cout<<(ans+1)%mod<<endl;//%lxq
}
return 0;
}

比赛时疯狂瞎改,想尽了所有加快的方法,加了tire之后跑得超快,直接第一.....

NAIPC2018的更多相关文章

随机推荐

  1. 输入框中提示信息(html5)

    placeholder 属性规定可描述输入字段预期值的简短的提示信息(比如:一个样本值或者预期格式的短描述). 该提示会在用户输入值之前显示在输入字段中. 注意:placeholder 属性适用于下面 ...

  2. URAL_1018 Binary Apple Tree 树形DP+背包

    这个题目给定一棵树,以及树的每个树枝的苹果数量,要求在保留K个树枝的情况下最多能保留多少个苹果 一看就觉得是个树形DP,然后想出 dp[i][j]来表示第i个节点保留j个树枝的最大苹果数,但是在树形过 ...

  3. spring boot 环境配置(profile)切换

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

  4. NET CLR via C#(第4版)第4章 类型基础

    本章内容: 1 所有类型都从System.Object派生 2 类型转换 3 命名空间和程序集 4 运行时的相互关系   本章讲述使用类型和CLR时需掌握的基础知识.具体地说,要讨论所有类型都具有的一 ...

  5. zabbix获取到的数值大于1000之后自动转换成1k

    问题:zabbix在取到的值很大时会自动变成K,M,G 解决方法: 1.修改/var/www/html/zabbix/include/func.inc.php文件(这个文件不一定在这,自己find找下 ...

  6. HDU-2087 C - 剪花布条(KMP基本)

    http://acm.hdu.edu.cn/showproblem.php?pid=2087 一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案.对于给定的花布条和小饰条,计算一下能 ...

  7. MySQL--索引和外键

    来自:http://www.jb51.net/article/32149.htm 1.添加PRIMARY KEY(主键索引)  ALTER TABLE `table_name` ADD PRIMARY ...

  8. Java中常用的API(二)——String

    在第一节中我们介绍了Object类的方法以及操作,那么这一节,我们将介绍一个新的类:String. String类是我们经常使用的类,应用十分广泛.同时,String类中封装了一系列的方法,非常常用, ...

  9. 插曲 强大的神器 vmware

    电脑到了  这连天给电脑配环境变量  真的想死  发现用 虚拟机 直接跑别人配置好的镜像文件   多快好省超级开心 比较毒瘤的  clion  不仅要配置c++ 环境  还要走cmake  等一堆东西 ...

  10. Python笔记_第四篇_高阶编程_检测_2.对类进行单元检测

    1. 对类进行单元检测: 第一步:首先编写一个类: # 类名Person,person.py class Person(object): def __init__(self,name,age): se ...