您的位置:首页 > 大数据 > 人工智能

Hdu 2015 Multi-University Training Contest7

2015-08-12 12:13 459 查看

1003

题面

Problem Description

Hotaru Ichijou recently is addicated to math problems. Now she is playing with N-sequence.

Let’s define N-sequence, which is composed with three parts and satisfied with the following condition:

1. the first part is the same as the thrid part,

2. the first part and the second part are symmetrical.

for example, the sequence 2,3,4,4,3,2,2,3,4 is a N-sequence, which the first part 2,3,4 is the same as the thrid part 2,3,4, the first part 2,3,4 and the second part 4,3,2 are symmetrical.

Give you n positive intergers, your task is to find the largest continuous sub-sequence, which is N-sequence.

Input

There are multiple test cases. The first line of input contains an integer T(T<=20), indicating the number of test cases.

For each test case:

the first line of input contains a positive integer N(1<=N<=100000), the length of a given sequence

the second line includes N non-negative integers ,each interger is no larger than 109 , descripting a sequence.

Output

Each case contains only one line. Each line should start with “Case #i: ”,with i implying the case number, followed by a integer, the largest length of N-sequence.

We guarantee that the sum of all answers is less than 800000.

Sample Input

1

10

2 3 4 4 3 2 2 3 4 4

Sample Output

Case #1: 9

题意

给一个长度为n(10^5)的序列,求一个最长的子序列,满足以下条件:

这个序列由三段组成,第一段与第二段对称,第一段与第二段相同。

比如:1 2 3 3 2 1 1 2 3。就是一个长度为9的串。

解析

一年前做过两道最长回文串的题,然后就忘得一干二净- -

最长回文串O(n)算法

这题就完全考这个算法的理解了。

先用manacher算法把每个位置的最长回文串找出来,然后枚举第二段的起点和长度,不断更新就行了。

枚举长度的时候相当于加个剪枝。

样例详解:

首先输入了一个串:

i0123456789
oldStr2344322344
接着将原串预处理,并由Manacher算法计算出每个下标下的最大回文串长度P[i]:

i012345678910111213141516171819202122
newStr-inf#2#3#4#4#3#2#2#3#4#4#inf
p[i]01212127212129212123211
由于题目要求所以应该从下标i应该从1开始枚举1,3,5,…的p[i],长度j也每次+=2去枚举p[i+j-1]这个位置#号的最大回文串,若当前长度j<=p[i + j - 1]的话,表示当前这个位置的回文串把前面的都包含进去了,所以更新最大值就行了。

最后由于我的长度是处理后的长度,为原来的2倍,所以/2*3就行了。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <climits>
#include <cassert>
#define LL long long
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define lson lo, mi, rt << 1
#define rson mi + 1, hi, rt << 1 | 1

using namespace std;
const int maxn = 100000 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double ee = exp(1.0);

int oldstr[maxn];
int newstr[maxn << 1];
int p[maxn << 1];

int Pre(int n)
{
int head = -inf;
int middle = -1;
int end = inf;
int len = 0;

newstr[len++] = head;
newstr[len++] = middle;
for(int i = 0; i < n; i ++)
{
newstr[len++] = oldstr[i];
newstr[len++] = middle;
}
newstr[len++] = end;
return len;
}

int Manacher(int len)
{
int MaxID = 0;
int MaxL = 0;
int id = 1;
p[0] = 0;
for(int i = 1; i < len; i ++)
{
if(MaxID > i)
p[i] = min(p[2 * id - i], MaxID - i);
else
p[i] = 1;
while(newstr[i - p[i]] == newstr[i + p[i]])
p[i] ++;
if(p[i] + i > MaxID)
{
MaxID = p[i] + i;
id = i;
}
if(p[i] > MaxL)
{
MaxL = p[i];
}
}
return MaxL - 1;
}

int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
int ncase;
int ca = 1;
scanf("%d", &ncase);
while (ncase--)
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d", &oldstr[i]);
}
int len = Pre(n);
Manacher(len);
int ans = 1;
for (int i = 1; i < len; i += 2)
{
//            cout << p[i] << " ";
for (int j = ans; j <= p[i]; j += 2)
{
if (j <= p[i + j - 1])
{
ans = j;
}
}
}
ans = ans / 2 * 3;
printf("Case #%d: ", ca++);
cout << ans << endl;
}
return 0;
}


1005

题面

Problem Description

In this problem, we should solve an interesting game. At first, we have an integer n, then we begin to make some funny change. We sum up every digit of the n, then insert it to the tail of the number n, then let the new number be the interesting number n. repeat it for t times. When n=123 and t=3 then we can get 123->1236->123612->12361215.

Input

Multiple input.

We have two integer n (0<=n<=104 ) , t(0<=t<=105) in each row.

When n==-1 and t==-1 mean the end of input.

Output

For each input , if the final number are divisible by 11, output “Yes”, else output ”No”. without quote.

Sample Input

35 2

35 1

-1 -1

Sample Output

Case #1: Yes

Case #2: No

题意

给一个数n,按题中描述模拟t次。

问最后结果能不能被11整除。

当n=123 and t=3 时,123->1236->123612->12361215.

解析

直接模拟竟然能过。。。

整除11的数的性质是这个数奇数位的和 和 偶数位的和 的差能被11整除。

然后队友写超时了0 0.

代码

模拟:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <climits>
#include <cassert>
#define LL long long
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define lson lo, mi, rt << 1
#define rson mi + 1, hi, rt << 1 | 1

using namespace std;
const int maxn = 100000 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double ee = exp(1.0);

int getSum(int x)
{
int res = 0;
while (x)
{
res += x % 10;
x /= 10;
}
return res;
}

int wei(int x)
{
int cnt = 0;
while (x)
{
x /= 10;
cnt++;
}
return cnt;
}

int fun(int x)
{
int res = 1;
for (int i = 0; i < x; i++)
{
res *= 10;
}
return res;
}

int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
int n, t;
int ca = 1;
while (~scanf("%d%d", &n, &t))
{
if (n + t == -2)
break;
int sum = getSum(n);
int num = n % 11;
while (t--)
{
num = num * fun(wei(sum)) + sum;
sum += getSum(sum);
num %= 11;
}
if (num)
printf("Case #%d: No\n", ca++);
else
printf("Case #%d: Yes\n", ca++);
}
return 0;
}


1007

题面

Problem Description

The reflected binary code, also known as Gray code after Frank Gray, is a binary numeral system where two successive values differ in only onebit (binary digit). The reflected binary code was originally designed to prevent spurious output from electromechanical switches. Today, Gray codes are widely used to facilitate error correction in digital communications such as digital terrestrial television and some cable TV systems.



Now , you are given a binary number of length n including ‘0’ , ’1’ and ‘?’(? means that you can use either 0 or 1 to fill this position) and n integers(a1,a2,….,an) . A certain binary number corresponds to a gray code only. If the ith bit of this gray code is 1,you can get the point ai.

Can you tell me how many points you can get at most?

For instance, the binary number “00?0” may be “0000” or “0010”,and the corresponding gray code are “0000” or “0011”.You can choose “0000” getting nothing or “0011” getting the point a3 and a4.

Input

The first line of the input contains the number of test cases T.

Each test case begins with string with ‘0’,’1’ and ‘?’.

The next line contains n (1<=n<=200000) integers (n is the length of the string).

a1 a2 a3 … an (1<=ai<=1000)

Output

For each test case, output “Case #x: ans”, in which x is the case number counted from one,’ans’ is the points you can get at most

Sample Input

2

00?0

1 2 4 8

????

1 2 4 8

Sample Output

Case #1: 12

Case #2: 15

Hint

https://en.wikipedia.org/wiki/Gray_code

http://baike.baidu.com/view/358724.htm

题意

给一个二进制数,其中包含?的地方可以是0,也可以是1。

然后问这个二进制数转换成格雷码,每位为1的权值相加最大为多少。

解析

模拟贪心。

开始的时候用前缀和求一直错一直错,然后突然发现其实中间的时候可以控制放弃最小权值的那个数。

然后又写,然后fr,to写晕了,换成了i,j。。。

然后又wa,一只wa,找不到原因。

然后全部推了重写,然后就过了,莫名其妙。。。

dp也行吧。。。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <climits>
#include <cassert>
#define LL long long
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define lson lo, mi, rt << 1
#define rson mi + 1, hi, rt << 1 | 1

using namespace std;
const int maxn = 200000 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double ee = exp(1.0);

char str[maxn];
int a[maxn];

int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
int ca = 1;
int ncase;
scanf("%d", &ncase);
while (ncase--)
{
scanf("%s", str);
int n = strlen(str);

for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}

int ans = 0;
int i, j;
for (i = 0; i < n; i++)
{
if (str[i] != '?')
continue;

int las, pre;
int cnt = 0;
if (i == 0)
pre = 0;
else
pre = str[i - 1] - '0';

for (j = i; j < n; j++)
{
if (str[j] == '?')
cnt++;
else
break;
}

las = str[j] - '0';
if (j == n)
{
for (; i < j; i++)
ans += a[i];
}
else if (las == pre)
{
if (cnt & 1)
{
for (; i <= j; i++)
ans += a[i];
}
else
{
int minn = inf;
for (; i <= j; i++)
{
ans += a[i];
minn = min(minn, a[i]);
}
ans -= minn;
}
}
else
{
if (cnt & 1)
{
int minn = inf;
for (; i <= j; i++)
{
ans += a[i];
minn = min(minn, a[i]);
}
ans -= minn;
}
else
{
for (; i <= j; i++)
ans += a[i];
}
}
i = j;
}
for (int i = 0; i < n; i++)
{
if (str[i] == '0')
{
if (i != 0 && str[i - 1] == '1')
ans += a[i];
}
else if (str[i] == '1')
{
if (i == 0 || (i != 0 && str[i - 1] == '0'))
ans += a[i];
}
}
printf("Case #%d: %d\n", ca++, ans);
}
return 0;
}


1011

题面

Problem Description

Little sun is an artist. Today he is playing mahjong alone. He suddenly feels that the tree in the yard doesn’t look good. So he wants to decorate the tree.(The tree has n vertexs, indexed from 1 to n.)

Thought for a long time, finally he decides to use the mahjong to decorate the tree.

His mahjong is strange because all of the mahjong tiles had a distinct index.(Little sun has only n mahjong tiles, and the mahjong tiles indexed from 1 to n.)

He put the mahjong tiles on the vertexs of the tree.

As is known to all, little sun is an artist. So he want to decorate the tree as beautiful as possible.

His decoration rules are as follows:

(1)Place exact one mahjong tile on each vertex.

(2)The mahjong tiles’ index must be continues which are placed on the son vertexs of a vertex.

(3)The mahjong tiles’ index must be continues which are placed on the vertexs of any subtrees.

Now he want to know that he can obtain how many different beautiful mahjong tree using these rules, because of the answer can be very large, you need output the answer modulo 1e9 + 7.

Input

The first line of the input is a single integer T, indicates the number of test cases.

For each test case, the first line contains an integers n. (1 <= n <= 100000)

And the next n - 1 lines, each line contains two integers ui and vi, which describes an edge of the tree, and vertex 1 is the root of the tree.

Output

For each test case, output one line. The output format is “Case #x: ans”(without quotes), x is the case number, starting from 1.

Sample Input

2

9

2 1

3 1

4 3

5 3

6 2

7 4

8 7

9 3

8

2 1

3 1

4 3

5 1

6 4

7 5

8 4

Sample Output

Case #1: 32

Case #2: 16

题意

给一棵编号1~n(10^5)的树,然后你可以用1~n的麻将去装饰这棵树,装饰的规则如下:

1.一个父亲节点的每个子节点的编号拿出来排序完了以后要是连续的;

2.每棵子树的每个节点的编号拿出来排序完了以后要是连续的;

3.每个麻将只用一次。

现在问在以上条件下,有多少种装饰这棵树的方法。

解析

先借样例理解一下题意。

如样例2,下图同一框框中的节点都要满足以上3个条件。



现在定义,一个父节点下可以有两种节点,一种是leaf(( •̀ ω •́ )y叶子节点),一种是child(有儿子的儿子节点)。

在计算样例的时候发现,在一个父节点下,只能存在至多两个child节点,而leaf节点可以任意个。因为child节点下的子树要满足以上条件2,并且child的兄弟节点要满足以上条件1,所以在这一层当中,一个取当前层连续段的开头,一个取当前层连续段的结尾,而如果出现三个及以上child节点的时候,不可能满足以上条件1,2。

接着就去计算每一个子树的根对总体的贡献,如果当前根下存在child节点,则ans = (2 * ans * fact[leaf]) % mod;

反之,ans = (ans * fact[leaf]) % mod。

然后这题,爆栈一发,不手动扩栈要爆;

mod坑了一发,判断不存在的拜访次数条件一发,最后*2取模一发。。。

代码

#pragma comment(linker, "/STACK:1677721600")
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <climits>
#include <cassert>
#define LL long long
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define lson lo, mi, rt << 1
#define rson mi + 1, hi, rt << 1 | 1

using namespace std;
const int maxn = 100000 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double ee = exp(1.0);

const int mod = 1e9 + 7;

int n;
bool vis[maxn];
vector<int> g[maxn];
LL ans;
LL fact[maxn];

bool error;

void factTable()
{
fact[0] = 1;
for (int i = 1; i < maxn; i++)
{
fact[i] = (fact[i - 1] * i) % mod;
}
}

void dfs(int rt)
{
if (error)
return;
int sz = g[rt].size();
int leaf = 0;
int child = 0;
for (int i = 0; i < sz; i++)
{
int v = g[rt][i];
if (!vis[v])
{
vis[v] = true;
if (g[v].size() >= 2)
{
child++;
if (child > 2)
{
error = true;
return;
}
dfs(v);
}
else
{
leaf++;
}
}
}
if (child > 2)
{
error = true;
return;
}
//    cout << "rt:" << rt << " leaf:" << leaf << " chil:" << chil << endl;
if (child == 0)
ans = (ans * fact[leaf]) % mod;
else
ans = (2 * ans * fact[leaf]) % mod;
}

int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
factTable();
int ncase;
scanf("%d", &ncase);
int ca = 1;
while (ncase--)
{
scanf("%d", &n);
memset(vis, false, sizeof(vis));
for (int i = 1; i <= n; i++)
{
g[i].clear();
}
for (int i = 0; i < n - 1; i++)
{
int fr, to;
scanf("%d%d", &fr, &to);
g[fr].push_back(to);
g[to].push_back(fr);
}
vis[1] = true;
ans = 1;
error = false;
dfs(1);
if (error)
{
printf("Case #%d: 0\n", ca++);
continue;
}
if (n > 1)
ans <<= 1;
printf("Case #%d: %lld\n", ca++, ans % mod);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: