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. 多线程开发之NSThrea

    创建并启动 先创建线程,再启动 // 创建   NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector( ...

  2. SASS - 函数

    SASS – 简介 SASS – 环境搭建 SASS – 使用Sass程序 SASS – 语法 SASS – 变量 SASS- 局部文件(Partial) SASS – 混合(Mixin) SASS ...

  3. Day 11:静态导入、增强for循环、可变参数的自动装箱与拆箱

    jdk1.5新特性-------静态导入 静态导入的作用: 简化书写. 静态导入可以作用一个类的所有静态成员.  静态导入的格式:import static 包名.类名.静态的成员: 静态导入要注意的 ...

  4. 【转】pip升级不成功怎么办

    python -m pip install --upgrade pip -i https://pypi.douban.com/simple

  5. [GXYCTF2019]禁止套娃

    0x00 知识点 无参数RCE eval($_GET['exp']); 参考链接: https://skysec.top/2019/03/29/PHP-Parametric-Function-RCE/ ...

  6. 新发布的廉价版iPhoneXR值得购买吗?

    每年苹果九月份的发布会,都是一场声势浩大的全民狂欢"大趴体".其中最兴奋的,自然就是各路段子手--就指望着苹果发布会来提供一年的笑料呢!而今年苹果发布会召开之后,网上最流行的就是下 ...

  7. 2020牛客寒假算法基础集训营4 H坐火车

    题目描述 牛牛是一名喜欢旅游的同学,在来到渡渡鸟王国时,坐上了颜色多样的火车. 牛牛同学在车上,车上有 n 个车厢,每一个车厢有一种颜色. 他想知道对于每一个正整数 $ x \in [1,\ n] $ ...

  8. UVM实战[二]

    本期将讲解UVM环境构成和启动方式.主要参考资料为 http://bbs.eetop.cn/thread-320165-1-1.html http://rockeric.com/ 环境构成 进行仿真验 ...

  9. 2019.3.12 linux关于用户的一些命令

    su:默认切换到root 创建用户 adduser :新建一个用户 sudo adduser 新用户名字 :创建新用户 sudo passwd 用户名:修改该用户名的密码 创建组 sudo addgr ...

  10. Android aar同步Failed to resolve: :nuisdk:

    在app.gradle中android.dependencies同一级别下加入: repositories { flatDir { dirs 'libs' } }