6/12

2016 Multi-University Training Contest 4
官方题解

KMP+DP A Another Meaning(CYD)

题意:

给一段字符,同时给定你一个单词,这个单词有双重意思,字符串中可能会有很多这种单词,求这句话的意思总数:hehe。

思路:

可以用kmp算法快速求出串中的单词数量,若单词是分开的,每个单词有两种意思,可以直接相乘,若两个及以上单词在原串中是有交集的,那么数量不是直接相乘,发现这片连在一起的单词数量dp[i]=dp[i-1]+dp[j];若i是连在一起的第一个数,dp[i]是2,j是与i不直接相连的最大那个单词位置,若这串的第一个单词也与之相连,那么dp[j]=1;这样就可以算出总数了。

代码:

#include <bits/stdc++.h>
using namespace std; const int maxn=100005;
const long long mod=1000000007; int f[maxn],n,m,s;
int a[maxn];
long long b[maxn];
char P[maxn],T[maxn]; void getFail()
{
f[0]=0;f[1]=0;
for(int i=1;i<m;i++)
{
int j=f[i];
while(j && P[i]!=P[j])
j=f[j];
f[i+1]= P[i] == P[j] ? j+1 : 0;
}
} int main()
{
int t,cas=1;
int i,j;
scanf("%d",&t); while(t--)
{
memset(f,0,sizeof(f));
s=0;
b[0]=1;a[0]=-1; scanf("%s",T);
scanf("%s",P); n=strlen(T),m=strlen(P);
getFail();
long long ans=1;
int cnt=0,line=-1;
j=0;
for(i=0;i<n;i++)
{
while(j && P[j]!=T[i]) j=f[j];
if(P[j]==T[i]) j++;
if(j==m)
{
if(i-m+1>line)
{
ans=(ans*b[s])%mod;
a[++s]=i;
b[s]=2;
cnt=1,line=i;
}
else
{
int k=lower_bound(a+1,a+1+s,i-m+1)-a;
long long c=b[k-1];
if(s-k+1>=cnt)
c=1;
a[++s]=i;
b[s]=(c+b[s-1])%mod;
cnt++,line=i;
}
j=0,i=i-m+1;
}
}
ans=(ans*b[s])%mod;
printf("Case #%d: %I64d\n",cas++,ans);
}
return 0;
}

中国剩余定理+容斥原理 E Lucky7(BH)

题意:

  问[L,R]区间内所有满足条件的数的个数,条件:and

思路:

  看到n的范围应该能想到可以用状态压缩来枚举(pi,ai)的组合,求这个有什么用呢?可以从反面考虑,先求出“在[L,R]范围内,是7的倍数且”的个数,然后用”是7的倍数“的个数减之就是答案。前者可以用中国剩余定理以及状态压缩枚举方程组来得到,注意要是在7的倍数的条件下,所以每次取出的方程组一定要有(p=7, a=0)的方程组。另外,小于n的个数内是k的倍数的个数为n/k。

代码:

#include <bits/stdc++.h>

typedef long long ll;
const int N = 20;
ll a[N], m[N];
ll ta[N], tm[N];
ll L, R;
int n, k; void ex_GCD(ll a, ll b, ll &x, ll &y, ll &d) {
if (!b) {
x = 1; y = 0; d = a;
} else {
ex_GCD (b, a % b, y, x, d);
y -= a / b * x;
}
} ll mul_mod(ll a, ll b, ll mod) {
ll ret = 0;
a = (a % mod + mod) % mod;
b = (b % mod + mod) % mod;
while (b) {
if (b & 1) {
ret += a;
if (ret >= mod) ret -= mod;
}
b >>= 1;
a <<= 1;
if (a >= mod) a -= mod;
}
return ret;
} ll M;
ll China(int k, ll *a, ll *m) {
ll x, y, ret = 0, d;
for (int i=0; i<=k; ++i) {
ll w = M / m[i];
ex_GCD (w, m[i], x, y, d);
ret = (ret + mul_mod (mul_mod (x, w, M), a[i], M));
}
return (ret + M) % M;
} ll solve(ll x) {
if (x == 0) return 0;
ll sub = 0;
int S = 1 << n;
ta[0] = 0; tm[0] = 7;
for (int i=1; i<S; ++i) {
int k = 0;
M = 7;
for (int j=0; j<n; ++j) {
if (i & (1 << j)) {
ta[++k] = a[j];
tm[k] = m[j];
M *= m[j];
}
}
ll res = China (k, ta, tm);
if (x < res) continue;
if (k & 1) sub -= (x - res) / M + 1;
else sub += (x - res) / M + 1;
}
//ret < 0
return x / 7 + sub;
} int main() {
int T;
scanf ("%d", &T);
for (int cas=1; cas<=T; ++cas) {
scanf ("%d%I64d%I64d", &n, &L, &R);
for (int i=0; i<n; ++i) {
scanf ("%I64d%I64d", m+i, a+i);
}
printf ("Case #%d: %I64d\n", cas, solve (R) - solve (L-1));
}
return 0;
}

后缀数组 F Substring(BH)

题意:

  问一个字符串里至少包含一个字符X的不同的子串的个数。

思路:

  后缀数组可以较方便的处理LCP(最长公共前缀)。方法如下图所示:设有一个字符串为"aabaaaab",可以对所有后缀按照字典序从小到大排序,排好序后相邻的后缀的相同前缀长度就是它们的LCP,那么这题要求不相同的子串,所以这些相同的前缀肯定不能多次统计,比如aab和aabaaaab,b是要求字符,那么aab只能统计一次,对于aabaaaab它能贡献的子串只能是aabaaaab。如果要求字符X,只需要记录距离后缀i最近的字符X的位置。

代码:

#include <bits/stdc++.h>

typedef long long ll;
const int N = 1e5 + 5; struct Suffix_Array {
int n, len, s[N];
int sa[N], rank[N], height[N];
int tmp_one[N], tmp_two[N], c[N]; void init_str(char *str);
void build_sa(int m = 128);
void get_height(); void print();
}SA; void Suffix_Array::print() {
puts ("sa[] and height[]:");
for (int i=0; i<n; ++i) {
printf ("%2d ", sa[i]);
}
puts ("");
for (int i=0; i<n; ++i) {
printf ("%2d ", height[i]);
}
puts ("");
} char str[N];
int nex[N];
char q[2]; ll solve() {
SA.init_str (str);
SA.build_sa ();
SA.get_height (); ll ret = 0;
int len = SA.len;
nex[len] = len;
for (int i=len-1; i>=0; --i) {
nex[i] = str[i] == q[0] ? i : nex[i+1];
}
for (int i=1; i<=len; ++i) {
ret += (len - 1) - std::max (SA.sa[i] + SA.height[i], nex[SA.sa[i]]) + 1;
}
return ret;
} int main() {
int T;
scanf ("%d", &T);
for (int cas=1; cas<=T; ++cas) {
scanf ("%s", &q);
scanf ("%s", &str);
printf ("Case #%d: %I64d\n", cas, solve ());
}
return 0;
} void Suffix_Array::init_str(char *str) {
n = 0;
len = strlen (str);
for (int i=0; i<len; ++i) {
s[n++] = str[i] - 'a' + 1;
}
s[n++] = 0; //n = strlen (str) + 1
} void Suffix_Array::get_height() {
for (int i=0; i<n; ++i) rank[sa[i]] = i;
int k = height[0] = 0;
for (int i=0; i<n-1; ++i) {
if (k) k--;
int j = sa[rank[i]-1];
while (s[i+k] == s[j+k]) k++;
height[rank[i]] = k;
}
} //m = max (r[i]) + 1,一般字符128足够了
void Suffix_Array::build_sa(int m) {
int i, j, p, *x = tmp_one, *y = tmp_two;
for (i=0; i<m; ++i) c[i] = 0;
for (i=0; i<n; ++i) c[x[i]=s[i]]++;
for (i=1; i<m; ++i) c[i] += c[i-1];
for (i=n-1; i>=0; --i) sa[--c[x[i]]] = i;
for (j=1, p=1; p<n; j<<=1, m=p) {
for (p=0, i=n-j; i<n; ++i) y[p++] = i;
for (i=0; i<n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j;
for (i=0; i<m; ++i) c[i] = 0;
for (i=0; i<n; ++i) c[x[y[i]]]++;
for (i=1; i<m; ++i) c[i] += c[i-1];
for (i=n-1; i>=0; --i) sa[--c[x[y[i]]]] = y[i];
std::swap (x, y);
for (p=1, x[sa[0]]=0, i=1; i<n; ++i) {
x[sa[i]] = (y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+j] == y[sa[i]+j] ? p - 1 : p++);
}
}
}

贪心+LIS J The All-purpose Zero

题意:

有一串数,其中0可以变为任意整数,最长上升子序列是多长。

思路:

0可以转换成任意任何整数,就是说也可以转换为负数,那么最长上升子序列包含的数值一定含有全部0,那么就看其余正整数能否在数列中,也就是说是否会和0变化成的数字冲突,那么我们可以将每个权值S[i]减去i前面0的个数这个方法组成新的数列做LIS(O(nlogn)),最后加上0的数量。

代码:

#include <bits/stdc++.h>
using namespace std; const int inf=0x3f3f3f3f; int s[100005],m,dp[100005]; int main()
{
int T,cas=1;
int i,j,k;
int n,num,x,ma;
scanf("%d",&T);
while(T--)
{
for(i=0;i<=100002;i++)
{
dp[i]=inf;
} m=0,num=0,ma=0;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&x);
if(x==0)
{
num++;
}
else
{
s[++m]=x-num;
}
} for(i=1;i<=m;i++)
{
int l=lower_bound(dp+1,dp+n+1,s[i])-dp;
dp[l]=s[i];
ma=max(l,ma);
} printf("Case #%d: %d\n",cas++,ma+num);
}
return 0;
}

  

2016 Multi-University Training Contest 4的更多相关文章

  1. 2016 Al-Baath University Training Camp Contest-1

    2016 Al-Baath University Training Camp Contest-1 A题:http://codeforces.com/gym/101028/problem/A 题意:比赛 ...

  2. 2016 Al-Baath University Training Camp Contest-1 E

    Description ACM-SCPC-2017 is approaching every university is trying to do its best in order to be th ...

  3. 2016 Al-Baath University Training Camp Contest-1 A

    Description Tourist likes competitive programming and he has his own Codeforces account. He particip ...

  4. 2016 Al-Baath University Training Camp Contest-1 J

    Description X is fighting beasts in the forest, in order to have a better chance to survive he's gon ...

  5. 2016 Al-Baath University Training Camp Contest-1 I

    Description It is raining again! Youssef really forgot that there is a chance of rain in March, so h ...

  6. 2016 Al-Baath University Training Camp Contest-1 H

     Description You've possibly heard about 'The Endless River'. However, if not, we are introducing it ...

  7. 2016 Al-Baath University Training Camp Contest-1 G

    Description The forces of evil are about to disappear since our hero is now on top on the tower of e ...

  8. 2016 Al-Baath University Training Camp Contest-1 F

    Description Zaid has two words, a of length between 4 and 1000 and b of length 4 exactly. The word a ...

  9. 2016 Al-Baath University Training Camp Contest-1 D

    Description X is well known artist, no one knows the secrete behind the beautiful paintings of X exc ...

  10. 2016 Al-Baath University Training Camp Contest-1 C

    Description Rami went back from school and he had an easy homework about bitwise operations (and,or, ...

随机推荐

  1. RabbitMQ消息队列(一): Detailed Introduction 详细介绍

     http://blog.csdn.net/anzhsoft/article/details/19563091 RabbitMQ消息队列(一): Detailed Introduction 详细介绍 ...

  2. JSVirtualMachine与JSContext

    JSVirtualMachine相当于进程: JSContext相当于线程:

  3. C# 访问数据库

    1. 首先引用和生命system.data.sqlClient 2. 使用sqlconnect类链接,sqlcommand类执行SQL命令,最后结果返回给sqlDataReader类或者是其他类 3. ...

  4. MyBatis学习总结(一)——MyBatis快速入门

    一.Mybatis介绍 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以 ...

  5. 【转载】使用pandas进行数据清洗

    使用pandas进行数据清洗 本文转载自:蓝鲸的网站分析笔记 原文链接:使用python进行数据清洗 目录: 数据表中的重复值 duplicated() drop_duplicated() 数据表中的 ...

  6. 【WIN10】绑定x:Bind

    在WP8.WP8中,我们知道有一个绑定{Binding},而在Win10中,新增了一个绑定{x:Bind} x:Bind :为编译时绑定 ,内存.内存相对于传统绑定都有优化 特性: 1.为强类型    ...

  7. Android高手速成--第二部分 工具库

    主要包括那些不错的开发库,包括依赖注入框架.图片缓存.网络相关.数据库ORM建模.Android公共库.Android 高版本向低版本兼容.多媒体相关及其他. 一.依赖注入DI 通过依赖注入减少Vie ...

  8. func_get_arg、func_get_args、func_num_args实现PHP伪重载

    今天在看书的时候,发现书上有这么一条:函数重载的替代方法——伪重载 确实,在PHP中没有函数重载这个概念,让很多时候我们无法进行一些处理,甚至有时候不得不在函数后面定义好N个参数在看到了func_ge ...

  9. 利用 autoconf 和 automake 生成 Makefile 文件

    一.相关概念的介绍 什么是 Makefile?怎么书写 Makefile?竟然有工具可以自动生成 Makefile?怎么生成啊?开始的时候,我有这么多疑问,所以,必须得先把基本的概念搞个清楚. 1.M ...

  10. 机器学习 k-临近算法

    程序清单一: from numpy import * import operator def creatDataSet(): group = array([[1.0,1.1],[1.0,1.0],[0 ...