dlutoj(自己家的OJ的一些不错的题)

来源:互联网 发布:painter软件百度云 编辑:程序博客网 时间:2024/06/04 18:41



1251: 最长公共子串

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 141  Solved: 33
[Submit][Status][Web Board]

Description

给定2个字符串,求这两个字符串的最长公共子串。

Input

第一行一个正整数T<=10代表输入数据个数
对于每组输入数据,
有两行字符串(每个字符串的长度小于100000,且该字符串的所有字母都是小写字母)

Output

输出最长公共子串的长度

Sample Input

2
abcde
cd
yeshowmuchiloveyoumydearmotherreallyicannotbelieveit
yeaphowmuchiloveyoumydearmother

Sample Output

2
27

HINT

Source

srssyd

这题就是找最长的公共子串,二分+哈希显然是可以做的,然而哈希之后扔进set里面查询稳稳TLE,于是就要手写hashtable

这题练习了如何写hashtable,其实就是用哈希值表示了一个字符串之后,扔进hashtable的时候,模mod,就像另外开了个地址存储这个哈希值,然后像链表一样存储这个哈希值。

当另外个字符串中算出一个哈希值的时候,模mod,然后进入到这个链表里面查询,如果链表里面有相同的哈希值,那么就说明找到了

算哈希值的时候可以用ull自动溢出,然后乘的数选择13333331等的质数就行(教主教导),然后在hashtable里mod的一个数最好大于这个字符串能产生的哈希值的个数,这个题给10W的字符串,所以1e5+7就300ms不到就跑完了orz

AC代码:http://paste.ubuntu.net/12892460/

如有时间,以后好好学习后缀数组等


1005: SNAGA

Time Limit: 1 Sec  Memory Limit: 32 MB
Submit: 87  Solved: 21
[Submit][Status][Web Board]

Description

Let us begin with a positive integer N and find the smallest positive integer which doesn't divide N. If we repeat the procedure with the resulting number, then again with the new result and so on, we will eventually obtain the number 2 (two). Let us define strength(N) as the length of the resulting sequence.

For example, for N = 6 we obtain the sequence 6, 4, 3, 2 which consists of 4 numbers, thus strength(6) = 4.

Given two positive integers A < B, calculate the sum of strengths of all integers between A and B(inclusive), that is,

strength(A) + strength(A + 1) + ... + strength(B).

Input

The first and only line of input contains two positive integers, A and B (3 ≤ A < B < 1017).

Output

The first and only line of output should contain the requested sum of strengths.

Sample Input

3 6

Sample Output

11

HINT

Source

COCI 2012/2013 Contest #1

这题看数据,就知道肯定是用类似前缀和的方法做,然后就是如何求了

就是想这个数如果不能被2整除,那么就长度就是t[2]+1,如果能被2整除,那就再考虑能不能被3整除。

依次这样考虑下去,就是前面一些连续的数的lcm,最多只有连续40多个数的lcm就超过1e17了,然后就打个表处理一下到这个数的时候,剩下多少个能被它整除的,再预处理这个数字到2的跳转的长度,然后程序就递归求一下就行了

AC代码 :http://paste.ubuntu.net/12987049/



1079: good串(1.3)

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 21  Solved: 10
[Submit][Status][Web Board]

Description

1.对于给定的一个长度是N的0,1字符串S = s1s2...sn。
2.S的子串S(l,r) = [sl,sl+1,sl+2,...,sr]。
3.若S(l,r)中'0'的个数是'1'个数的2倍,称S(l,r)这个为good串,否则为bad串。
选择一对整数a, b (1 <= a <= b <= N)。
Num1:开始位置l和结束位置r都在闭区间[a,b]上的子串中good串的个数;
Num2:开始位置l和结束位置r都不在闭区间[a,b]上的子串中good串的个数,但可以包含[a,b]子串,即l,r有如下三种情况l<a且r<a,l>b且r>b,l<a且r>b;
求有多少对a, b使得Num1与Num2相等?

Input

第一行输入一个整数N。1<=N<=100000;
第二行输入一个由’0’和’1’组成的长度为n的字符串。

Output

输出一个整数,即使Num1和Num2相等的a,b数对。

Sample Input

3
010

Sample Output

4

HINT

[a,b]=[1,1]时:

开始位置l和结束位置r都在闭区间[a,b]上的子串如下:

"0"(good子串的个数是0个)。

开始位置l和结束位置r都不在闭区间[a,b]上的子串如下:

"1","0","10"(good子串的个数是0个)。

所以[1,1]满足条件。


[a,b]=[1,2]时:

开始位置l和结束位置r都在闭区间[a,b]上的子串如下:

"0","1","01"(good子串的个数是0个)。

开始位置l和结束位置r都不在闭区间[a,b]上的子串如下:

"0"(good子串的个数是0个)。

所以[1,2]满足条件。


[a,b]=[1,3]时:

开始位置l和结束位置r都在闭区间[a,b]上的子串如下:

"0","1","0","01","10","010"(good子串的个数是1个:"010")。

不存在开始位置l和结束位置r都不在闭区间[a,b]上的子串(good子串的个数是0个)。

所以[1,3]不满足条件。


[a,b]=[2,2]时:

开始位置l和结束位置r都在闭区间[a,b]上的子串如下:

"1"(good子串的个数是0个)。

开始位置l和结束位置r都不在闭区间[a,b]上的子串如下:

"0","0","010"(good子串的个数是1个:"010")。

所以[2,2]不满足条件。


[a,b]=[2,3]时:

开始位置l和结束位置r都在闭区间[a,b]上的子串如下:

"1","0","10"(good子串的个数是0个)。

开始位置l和结束位置r都不在闭区间[a,b]上的子串如下:

"0"(good子串的个数是0个)。

所以[2,3]满足条件。


[a,b]=[3,3]时:

开始位置l和结束位置r都在闭区间[a,b]上的子串如下:

"0"(good子串的个数是0个)。

开始位置l和结束位置r都不在闭区间[a,b]上的子串如下:

"0","1","01"(good子串的个数是0个)。

所以[3,3]满足条件。


所以有4对a,b满足题意。

Source

sspa

这题是个不错的题,10W的数据量,让我不能暴力,或者说前缀和都不好遍历处理

10W应该是用nlogn的复杂度才能过

所以就想如何优化,首先前缀和之类的是肯定要处理的,所以就正着来一遍0和1的前缀和,倒着来一遍0和1的后缀和,然后用map维护,正着遍历一遍,用前缀和算,2*sum1-sum0这个值,说明这一段的0,1的个数,然后找map里面有没有这个值,有的话就说明,前面那段和这段中间这个区间,满足2*sum1==sum0,所以就可以用一个sumgood0数组记录在i左边的good串个数,然后map里面这个映射++

然后倒着来一遍,用后缀和求2*rsum1-rsum0,然后看map里面有没有,有的话就说明i的右边有good串,然后用sumgood1数组记录i右边的good串个数

最后就是找a,b的个数,这让也是不能用暴力枚举的,所以还是需要用map来维护。

我们前面做过good串5000的数据量的题,是用总的good串的个数,减去a右边的good串,减去b左边的good串,然后加上a左边的good串,再加上b右边的good串,如果等于0,就说明这对a,b是可以的,所以这次就是再次用map维护,先正着来一遍,求a右边的减去a左边的值x,然后倒着来一遍,求b左边的减去右边的y,然后用总数减去y放进map里面去求就行了。

wa了两次,有个地方要注意的就是,在上面求sumgood的时候,map[0]要设为1

AC代码:http://paste.ubuntu.net/13057073/


1093: 变换之美

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 62  Solved: 30
[Submit][Status][Web Board]

Description

有一个长度为N的整数数列(A1, A2…Ai…An-1, An)(-100<=Ai<=100),现在可以对该数列进行一种变换,即选择数列中的一个数字Ai(1<i<N),将Ai-1, Ai, Ai+1变换成 Ai-1+Ai, -Ai, Ai+1+Ai。这种变换操作可以进行多次。现在Bryan想知道一个数列能否变换成另一个数列。

Input

多组测试数据。

每组数据:

1行:一个正整数N(3<=N<=5000),表示数列的长度。

2行:N个整数,表示数列A

3行:N个整数,表示数列B

Output

对于每组数据:

如果数列A能变换成数列B,输出YES,否则,输出NO

Sample Input

3
1 2 3
1 2 3
5
1 2 3 4 5
5 4 3 2 1
5
1 2 3 4 5
6 -5 9 -7 12

Sample Output

YES
NO
YES

HINT

对于Case2的变换方式:


Step0:  1 2 3 4 5


Step1:  1 5 -3 7 5


Step2:  1 5 4 -7 12


Step3:  6 -5 9 -7 12


Source

Bryan

这题是个挺巧妙的题,你可以发现两个数列的前缀和

Si-1,Si,Si+1在变换之后变成了Si,Si-1,Si+1,所以直接输入的时候求两个数列的前缀和,然后排序之后比较就行了orz

AC代码:http://paste.ubuntu.net/13057208/



1327: Almost sorted interval

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 52  Solved: 11
[Submit][Status][Web Board]

Description

Shik loves sorted intervals. But currently he does not have enough time to sort all the numbers. So he decided to use Almost sorted intervals. An Almost sorted interval is a consecutive subsequence in a sequence which satisfies the following property:
The first number is the smallest.
The last number is the largest.
Please help him count the number of almost sorted intervals in this permutation.
Note: Two intervals are different if at least one of the starting or ending indices are different.

Input

Muti-case , for each case
The first line contains an integer N. 
The second line contains a permutation from 1 to N
1<=n<=10^6

Output

Output the number of almost sorted intervals.

Sample Input

5
3 1 2 5 4

Sample Output

8

HINT

Explanation 

The subsequences [3], [1], [1 2], [1 2 5], [2], [2 5], [5], [4] are almost sorted intervals.

Source


这题用两个单调栈维护,给你一个数列,让你求一段连续的区间,头上元素是区间里最小的,最后个元素是区间里最大的,然后有多少个这样的区间
先正着维护一个递增的单调栈,找到某个元素最右端能延伸到的位置,说明这个元素如果做区间的头元素的话,区间内都大于他的元素有多少
然后倒着维护一个递减的单调栈,每加入一个元素的时候,栈里的元素都比他大,然后二分找一下它最远延伸到的位置在栈里的什么位置,然后这个位置到栈顶的那些元素都可以当作区间的尾,因为栈是递减的,如果当前考虑的元素和栈里的元素之间有元素比栈里的这个元素大,那么栈里的元素会被弹出,所以这样维护是正确的
单调栈还需要多练习
AC代码:http://paste.ubuntu.net/13099852/

1187: wanghang的数论I

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 57  Solved: 16
[Submit][Status][Web Board]

Description

定义函数f满足:f(nm)=f(n)*f(m),f(1)=1,f(p)=i+1,其中p是第i个素数
比如:前5个素数是2,3,5,7,11,则f(2)=2,f(3)=3,f(5)=4,f(7)=5,f(11)=6
对于f(6),由于6=2*3所以f(6)=f(2*3)=f(2)*f(3)=6
又比如f(8),则f(8)=f(4)*f(2)=f(2)*f(2)*f(2)=8
即:
定义函数g(n)为所有x与n互素的f(x)的和,其中x为正整数且x<=n
即:
互素的定义为,如果两个正整数a和b的最大公约数为1,则称a和b是互素的。
给出n,求g(n)的值。
最后结果对1000000007取模

Input

第一行为一个正整数T<=1000,代表测试数据个数

然后T行每行一个正整数n,n<=1000000

Output

对每组测试数据,输出g(n)的值,结果对1000000007取模

Sample Input

2
3
4

Sample Output

3
4

HINT

 对于测试数据3,与3互素的数有1和2,则g(3)=f(1)+f(2)=3


对于测试数据4,与4互素的数有1和3,则g(4)=f(1)+f(3)=4


Source


这题是容斥原理,首先打表处理出素数,然后求出所有合数的f值,还要求f的前缀和用sum数组存起来,然后用容斥原理求解,因为一个数最多由6-7种不同的素数组成,所以直接二进制枚举,然后用容斥原理求解,(容斥感觉好屌啊,必须好好学习好好理解),然后求解的时候,因为考虑所有和n互素的数的f值,所以可以直接考虑所有n的情况,然后减去比如2的幂次,3的幂次(2的幂次的和可以用f[2]*sum[n/2]来表示,因为每个2的幂次都可以提出个2,然后根据题目定义,所以可以这样求),然后加上2和3的倍数的幂次啊,这样容斥,就OK了
AC代码:http://paste.ubuntu.net/13099908/
还有wanghang的数论3.是时候走一走了,莫比乌斯起

0 0
原创粉丝点击