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. Fibonacci 数列算法分析

    /************************************************* * Fibonacci 数列算法分析 ****************************** ...

  2. tyvj1034 尼克的任务

    描述 尼克每天上班之前都连接上英特网,接收他的上司发来的邮件,这些邮件包含了尼克主管的部门当天要完成的全部任务,每个任务由一个开始时刻与一个持续时间构成.尼克的一个工作日为N分钟,从第一分钟开始到第N ...

  3. 2014 Multi-University Training Contest 9#1009

    Just a JokeTime Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Tot ...

  4. 苹果微信下载 iOS微信各版本列表

    微信在不断地更新迭代,ios微信下载点击这里立即开始(手机电脑都可以,电脑端要安装iTunes),每个版本都放出一些新的功能或修复相关错误,详情可以点击下面的版本链接进行查看.(这里有Android微 ...

  5. PHP判断远程文件是否存在

    <?php /* 函数:remote_file_exists 功能:判断远程文件是否存在 参数: $url_file -远程文件URL 返回:存在返回true,不存在或者其他原因返回false ...

  6. 【推荐】MySQL Cluster报错及解决方法(不断更新中)

    排查问题技巧: MySQL Cluster 自带了一个错误代码的查看的小程序.通过这个小东西我们可以方便的定位问题的原因. 这个程序就是 perror 在MYSQL安装目录的bin下面. 如报错:ER ...

  7. MySQL 的 find_in_set 函数使用方法

    举个例子来说: 有个文章表里面有个type字段,它存储的是文章类型,有 1头条.2推荐.3热点.4图文...1,12,13 等等 . 现在有篇文章他既是 头条,又是热点,还是图文, type中以 1, ...

  8. 【Alpha版本】冲刺阶段——Day 2

    我说的都队 031402304 陈燊 031402342 许玲玲 031402337 胡心颖 03140241 王婷婷 031402203 陈齐民 031402209 黄伟炜 031402233 郑扬 ...

  9. 号外!GNOME 3.22 正式发布喽!!!

    导读 经过半年的努力开发,别名为“卡尔斯鲁厄”的 GNOME 3.22 正式发布了!“GNOME Software 可以安装和更新 Flatpak 软件包,GNOME Builder 则可以创建它们, ...

  10. highcharts的表名

    line:直线图 spline:曲线图 area:面积图 areaspline:曲线面积图 arearange:面积范围图 areasplinerange:曲线面积范围图 column:柱状图 col ...