Manthan Codefest 16 解题报告

苟蒻太懒了。。现在才写

A. Ebony and Ivory
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Dante is engaged in a fight with "The Savior". Before he can fight it with his sword, he needs to break its shields. He has two guns, Ebony and Ivory, each of them is able to perform any non-negative number of shots.

For every bullet that hits the shield, Ebony deals a units of damage while Ivory deals b units of damage. In order to break the shield Dante has to deal exactly c units of damage. Find out if this is possible.

Input

The first line of the input contains three integers abc (1 ≤ a, b ≤ 100, 1 ≤ c ≤ 10 000) — the number of units of damage dealt by Ebony gun and Ivory gun, and the total number of damage required to break the shield, respectively.

Output

Print "Yes" (without quotes) if Dante can deal exactly c damage to the shield and "No" (without quotes) otherwise.

Examples
input
4 6 15
output
No
input
3 2 7
output
Yes
input
6 11 6
output
Yes
Note

In the second sample, Dante can fire 1 bullet from Ebony and 2 from Ivory to deal exactly 1·3 + 2·2 = 7 damage. In the third sample, Dante can fire 1 bullet from ebony and no bullets from ivory to do 1·6 + 0·11 = 6 damage.



题意:

但丁用黑檀木和白象牙攻击,黑檀木每次射击造成a点伤害,而白象牙b点,但丁必须造成精确的x点伤害才能击败怪兽,问能否造成?


心爱的鬼泣。。帅气的但丁

一维背包判断存在性,不多提


#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;

const int maxn = 1E4 + 10;

int f[maxn],a,b,c;

int main()
{
	#ifdef YZY
		   freopen("yzy.txt","r",stdin);
	#endif
	
	cin >> a >> b >> c;
	f[0] = 1;
	for (int i = a; i <= c; i++)
		if (f[i-a])
			f[i] = 1;
	for (int i = b; i <= c; i++)
		if (f[i-b])
			f[i] = 1;
			
	if (f[c]) printf("Yes");
	else printf("No");
	
	return 0;
}


B. A Trivial Problem
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Mr. Santa asks all the great programmers of the world to solve a trivial problem. He gives them an integer m and asks for the number of positive integers n, such that the factorial of n ends with exactly m zeroes. Are you among those great programmers who can solve this problem?

Input

The only line of input contains an integer m (1 ≤ m ≤ 100 000) — the required number of trailing zeroes in factorial.

Output

First print k — the number of values of n such that the factorial of n ends with m zeroes. Then print these k integers in increasing order.

Examples
input
1
output
5
5 6 7 8 9 
input
5
output
0
Note

The factorial of n is equal to the product of all integers from 1 to n inclusive, that is n! = 1·2·3·...·n.

In the first sample, 5! = 1206! = 7207! = 50408! = 40320 and 9! = 362880.


题意:

给出整数n,问有多少个数的阶乘,刚好有n个后缀0


题解:

2*5 = 10有一个0不多说,当数字逐渐增大,其分解质因数后含有的2数量必远远大于5,所以统计5的个数即可


#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;

const int maxn = 1E5 + 10;

int ans[maxn],tot,m;

int main()
{
	#ifdef YZY
		   freopen("yzy.txt","r",stdin);
	#endif
	
	cin >> m;
	int sum = 0;
	for(int i = 5; ; i++) {
		int k = i;
		while (k % 5 == 0) k/=5,++tot;
		if (tot == m) ans[++sum] = i;
		if (tot > m) break;
	}
	printf("%d\n",sum);
	for (int i = 1; i <= sum; i++) printf("%d ",ans[i]);
	return 0;
}



C. Spy Syndrome 2
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

After observing the results of Spy Syndrome, Yash realised the errors of his ways. He now believes that a super spy such as Siddhant can't use a cipher as basic and ancient as Caesar cipher. After many weeks of observation of Siddhant’s sentences, Yash determined a new cipher technique.

For a given sentence, the cipher is processed as:

  1. Convert all letters of the sentence to lowercase.
  2. Reverse each of the words of the sentence individually.
  3. Remove all the spaces in the sentence.

For example, when this cipher is applied to the sentence

Kira is childish and he hates losing

the resulting string is

ariksihsidlihcdnaehsetahgnisol

Now Yash is given some ciphered string and a list of words. Help him to find out any original sentence composed using only words from the list. Note, that any of the given words could be used in the sentence multiple times.

Input

The first line of the input contains a single integer n (1 ≤ n ≤ 10 000) — the length of the ciphered text. The second line consists of nlowercase English letters — the ciphered text t.

The third line contains a single integer m (1 ≤ m ≤ 100 000) — the number of words which will be considered while deciphering the text. Each of the next m lines contains a non-empty word wi (|wi| ≤ 1 000) consisting of uppercase and lowercase English letters only. It's guaranteed that the total length of all words doesn't exceed 1 000 000.

Output

Print one line — the original sentence. It is guaranteed that at least one solution exists. If there are multiple solutions, you may output any of those.

Examples
input
30
ariksihsidlihcdnaehsetahgnisol
10
Kira
hates
is
he
losing
death
childish
L
and
Note
output
Kira is childish and he hates losing 
input
12
iherehtolleh
5
HI
Ho
there
HeLLo
hello
output
HI there HeLLo 
Note

In sample case 2 there may be multiple accepted outputs, "HI there HeLLo" and "HI there hello" you may output any of them.



题意:

Yash对自己的一段话加密:

1.将所有大写字母转成小写

2.将每个单词翻转

3.去除所有空格


现给出这段话中可能出现的一些单词,问这段话的原话是什么?

若有多种解输出任意一种


题解:

注意到单词数不超过1000000,考虑建立一棵trie

原话字符<=10000,那么从左到右for一遍尝试找解,又字符长度<=1000所以每个位置的查询向左1000位即可。tri可以以小写字符存储,找到存在的单词点输出对应位置原单词,降低编写难度

O(n*w)


#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;

const int maxn = 1E4 + 10;

struct T{
	int ch[26];
	int END;
	T () {
		memset(ch,0,sizeof(ch)); 
		END = 0;
	}
}t[1000010];

int cnt,n,m,f[maxn],last[maxn];
char x[maxn],y[1010];

vector <char> v[maxn*10];

void Insert(int o,int pos,int len,int num)
{
	for (; pos < len; pos++) {
		int to;
		if (y[pos] >= 'a') to = y[pos]-'a';
		else to = y[pos]-'A';
		if (!t[o].ch[to]) t[o].ch[to] = ++cnt;
		o = t[o].ch[to];
	}
	t[o].END = num;
}

void solve(int pos)
{
	int END = max(1,pos-999);
	int o = 0;
	for (int i = pos; i >= END; i--) {
		o = t[o].ch[x[i]-'a'];
		if (!o) break;
		if ((f[i-1] || i == 1) && t[o].END) {
			last[pos] = i;
			f[pos] = t[o].END; 
			break;
		}
	}
}

void pri(int pos)
{
	if (last[pos] != 1) pri(last[pos]-1);
	int len = v[f[pos]].size();
	for (int i = 0; i < len; i++) printf("%c",v[f[pos]][i]);
	printf(" ");
}

int main()
{
	#ifdef YZY
		   freopen("yzy.txt","r",stdin);
	#endif
	
	cin >> n;
	scanf("%s",1+x);
	cin >> m;
	for (int i = 1; i <= m; i++) {
		scanf("%s",&y);
		int len = strlen(y);
		Insert(0,0,len,i);
		for (int j = 0; j < len; j++) v[i].push_back(y[j]);
	}
	
	for (int i = 1; i <= n; i++) 
		solve(i);
	pri(n);
	return 0;
}


D. Fibonacci-ish
time limit per test
3 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

Yash has recently learnt about the Fibonacci sequence and is very excited about it. He calls a sequence Fibonacci-ish if

  1. the sequence consists of at least two elements
  2. f0 and f1 are arbitrary
  3. fn + 2 = fn + 1 + fn for all n ≥ 0.

You are given some sequence of integers a1, a2, ..., an. Your task is rearrange elements of this sequence in such a way that its longest possible prefix is Fibonacci-ish sequence.

Input

The first line of the input contains a single integer n (2 ≤ n ≤ 1000) — the length of the sequence ai.

The second line contains n integers a1, a2, ..., an (|ai| ≤ 109).

Output

Print the length of the longest possible Fibonacci-ish prefix of the given sequence after rearrangement.

Examples
input
3
1 2 -1
output
3
input
5
28 35 7 14 21
output
4
Note

In the first sample, if we rearrange elements of the sequence as  - 121, the whole sequence ai would be Fibonacci-ish.

In the second sample, the optimal way to rearrange elements is 28.



题意:

现有一个数组,从中任意选一些数构成一个斐波那契数列,问能够成的最长数列的长度是多少


题解:

一堆绝对值<=10^9的数用来构造斐波那契数列,虽然斐波那契数列增长不快,但是长度也不可能超过100,暴力枚举最开始的两个数,尝试能否构成即可

O(n^2)


用离散化存数的时候一开始没考虑到 f0 = f1的情形

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;

const int maxn = 1E3 + 10;
typedef long long LL;

int n,cur = 1,ans = 2,num[maxn],a[maxn],f[maxn],now[maxn];

void solve(int a,int b)
{
	int tot = 2;
	for (int i = 1; i <= cur; i++) now[i] = 0;
	++now[a]; ++now[b];
	a = num[a]; b = num[b];
	for (;;) {
		LL x = 1LL*a+1LL*b;
		if (x < -1000000000 || x > 1000000000) break;
		int c = a+b;
		int pos = lower_bound(num+1,num+cur+1,c)-num;
		if (num[pos] != c || f[pos] == now[pos]) break;
		++tot; ++now[pos];
		a = b; b = c;
	}
	ans = max(ans,tot);
}

int main()
{
	#ifdef YZY
		   freopen("yzy.txt","r",stdin);
	#endif
	
	cin >> n;
	for (int i = 1; i <= n; i++) {
		scanf("%d",&a[i]);
		num[i] = a[i];
	}
	sort(num+1,num+n+1);
	for (int i = 2; i <= n; i++)
		if (num[i] != num[i-1])
			num[++cur] = num[i];
			
	for (int i = 1; i <= cur; i++)
		for (int j = 1; j <= n; j++)
			if (num[i] == a[j])
				++f[i];
	
	for (int i = 1; i <= cur; i++)
		for (int j = 1; j <= cur; j++)
			if (i != j || f[i] > 1)
				solve(i,j);
	cout << ans;
	return 0;
}


E. Startup Funding
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

An e-commerce startup pitches to the investors to get funding. They have been functional for n weeks now and also have a website!

For each week they know the number of unique visitors during this week vi and the revenue ci. To evaluate the potential of the startup at some range of weeks from l to r inclusive investors use the minimum among the maximum number of visitors multiplied by 100 and the minimum revenue during this period, that is:

The truth is that investors have no idea how to efficiently evaluate the startup, so they are going to pick some k random distinct weeks liand give them to managers of the startup. For each li they should pick some ri ≥ li and report maximum number of visitors and minimum revenue during this period.

Then, investors will calculate the potential of the startup for each of these ranges and take minimum value of p(li, ri) as the total evaluation grade of the startup. Assuming that managers of the startup always report the optimal values of ri for some particular li, i.e., the value such that the resulting grade of the startup is maximized, what is the expected resulting grade of the startup?

Input

The first line of the input contains two integers n and k (1 ≤ k ≤ n ≤ 1 000 000).

The second line contains n integers vi (1 ≤ vi ≤ 107) — the number of unique visitors during each week.

The third line contains n integers ci (1 ≤ ci ≤ 107) —the revenue for each week.

Output

Print a single real value — the expected grade of the startup. Your answer will be considered correct if its absolute or relative error does not exceed 10 - 6.

Namely: let's assume that your answer is a, and the answer of the jury is b. The checker program will consider your answer correct, if .

Examples
input
3 2
3 2 1
300 200 300
output
133.3333333
Note

Consider the first sample.

If the investors ask for li = 1 onwards, startup will choose ri = 1, such that max number of visitors is 3 and minimum revenue is 300. Thus, potential in this case is min(3·100, 300) = 300.

If the investors ask for li = 2 onwards, startup will choose ri = 3, such that max number of visitors is 2 and minimum revenue is 200. Thus, potential in this case is min(2·100, 200) = 200.

If the investors ask for li = 3 onwards, startup will choose ri = 3, such that max number of visitors is 1 and minimum revenue is 300. Thus, potential in this case is min(1·100, 300) = 100.

We have to choose a set of size 2 equi-probably and take minimum of each. The possible sets here are :{200, 300},{100, 300},{100, 200}, effectively the set of possible values as perceived by investors equi-probably:{200, 100, 100}. Thus, the expected value is (100 + 200 + 100) / 3 = 133.(3).


题意:
现有两个数组v,c
对于每个l,找到合适的r使得p(l,r)的值最大
这样得到n个数,现在从中任选k个数组成一个可重集合,取集合最小的数作为这个集合的值,问这些值的期望值是多少?

题解:
对于确定l找r:
随着r的增加100*max vk是个增函数,min ck是个减函数,既然p(l,r)是取两者中的最小值,显 然两函数交点符合。由于交点不一定存在,所以最优解可能是左边一个或是右边一个。于是可以二 分,每个r用RMQ得到当前的v和c函数,判断c是否>v即可

我们得到了n个数,c(n,k)却巨大,连算出这个除数都难以保留。考虑将这n个数从小到大排序,如果第i个数是它所在集合的值,那么必定在[i+1,n]中找其余的k-1个数,于是
ans = ∑a[i]*c(n-i,k-1)/c(n,k)
又n*c(n-1,m-1) = m*c(n,m)
且c(n,m+1) = c(n,m)*(n-m)/m
通过这两个式子求解
O(nlogn) 二分、RMQ预处理复杂度,通过预处理RMQ区间长对应的log使RMQ查询复杂度为O(1)

一开始v函数没乘以100,数据强转类型没注意。。。

#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;

typedef double DB;
const int maxn = 1E6 + 10;

int n,a[maxn][20],b[maxn][20],c[maxn],LOG[maxn];

bool Judge(int l,int r)
{
	int len = LOG[r-l+1];
	int A = 100*max(a[l][len],a[r-(1<<len)+1][len]);
	int B = min(b[l][len],b[r-(1<<len)+1][len]);
	return A<B;
}

int main()
{
	#ifdef YZY
		freopen("yzy.txt","r",stdin);
	#endif
	
	int k;
	cin >> n >> k;
	for (int i = 1; i <= n; i++) scanf("%d",&a[i][0]);
	for (int i = 1; i <= n; i++) scanf("%d",&b[i][0]);
	for (int j = 1; j < 20; j++)
		for (int i = 1; i <= n; i++) {
			if (i + (1<<j-1) > n) break;
			a[i][j] = max(a[i][j-1],a[i+(1<<(j-1))][j-1]);
			b[i][j] = min(b[i][j-1],b[i+(1<<(j-1))][j-1]);
		}
		
	int now = 0,sum = 1;
	for (int i = 1; i <= n; i++) {
		if (sum >= i) LOG[i] = now-1;
		else {
			sum <<= 1;
			++now;
			LOG[i] = now-1;
		}
	}
	LOG[1] = 0;
	
	for (int i = 1; i <= n; i++) {
		int L,R; L = i; R = n;
		while (R - L > 1) {
			int mid = (L+R) >> 1;
			if (Judge(i,mid)) L = mid;
			else R = mid;
		}
	
		int len = LOG[L - i + 1];
		int A = 100*max(a[i][len],a[L-(1<<len)+1][len]);
		int B = min(b[i][len],b[L-(1<<len)+1][len]);
		c[i] = min(A,B);
		
		len = LOG[R - i + 1];
		A = 100*max(a[i][len],a[R-(1<<len)+1][len]);
		B = min(b[i][len],b[R-(1<<len)+1][len]);
		c[i] = max(c[i],min(A,B));
	}
	sort(c+1,c+n+1);
	
	DB ans = 0;
	DB N = n-1; DB M = k-1;
	DB v = (DB)(k)/(DB)(n);
	for (int i = 1; i <= n; i++) {
		if (n - i < k - 1) break;
		ans += v*(DB)(c[i]);
		v = v/N*(N-M);
		N -= 1.00;
	}
	printf("%.10f",ans);
	return 0;
}



F. The Chocolate Spree
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Alice and Bob have a tree (undirected acyclic connected graph). There are ai chocolates waiting to be picked up in the i-th vertex of the tree. First, they choose two different vertices as their starting positions (Alice chooses first) and take all the chocolates contained in them.

Then, they alternate their moves, selecting one vertex at a time and collecting all chocolates from this node. To make things more interesting, they decided that one can select a vertex only if he/she selected a vertex adjacent to that one at his/her previous turn and this vertex has not been already chosen by any of them during other move.

If at any moment one of them is not able to select the node that satisfy all the rules, he/she will skip his turns and let the other person pick chocolates as long as he/she can. This goes on until both of them cannot pick chocolates any further.

Due to their greed for chocolates, they want to collect as many chocolates as possible. However, as they are friends they only care about the total number of chocolates they obtain together. What is the maximum total number of chocolates they may pick?

Input

The first line of the input contains the single integer n (2 ≤ n ≤ 100 000) — the number of vertices in the tree.

The second line contains n integers ai (1 ≤ ai ≤ 109), i-th of these numbers stands for the number of chocolates stored at the node i.

Then follow n - 1 lines that describe the tree. Each of them contains two integers ui and vi (1 ≤ ui, vi ≤ n) — indices of vertices connected by the i-th edge.

Output

Print the number of chocolates Alice and Bob can collect together if they behave optimally.

Examples
input
9
1 2 3 4 5 6 7 8 9
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
output
25
input
2
20 10
1 2
output
30
Note

In the first sample, Alice may start at the vertex 9 and Bob at vertex 8. Alice will select vertex 1 and Bob has no options now. Alice selects the vertex 7 and they both stop.

In the second sample, both of them will pick either of the nodes alternately.


题意:
有一棵树每个节点有a个巧克力,现有两个好朋友在这棵树上走,两个人走的路径不能有交叉,他们所过之处不留下一个巧克力,问最多能收集多少个

题解:
树上dp。。简直了
一条路径肯定是从某叶节点开始向上,走到某节点后往下走到无法走,称最高处节点为祖先
1.两条路径祖先也有公共祖先
记ma[i]为以i为根的子树的最大路径,这种情况的解决就变成最大值+次大值
2.两条路径用祖孙关系
大概都可以描述成这种图

对于一些点2,这些点不在答案中。
显然最优解的右下部是一个ma[x]+最高处祖先往下的一段
记t[i]来维护这个东西,显然一颗子树的t[i]一确定,往上再怎么走最优解都是由许多个t[i]产生
于是t[i] = max{t[child]+a[i]} or a[i] + sum[m1] + sum[m2]
其中,sum[i]代表从某叶子到i节点路径最大值,m1,m2就是sum[ch]中的最大、次大
于是答案的计算就可以变成枚举每一个ch,找到除sum[ch]外的m1,m2,
ans = max{sum[m1] + sum[m2] + ma[ch]} or max{sum[m1] + t[ch]}

O(n)

因为标记未清0和long long的问题WA两发。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;

const int maxn = 1E5 + 10;

typedef long long LL;

int n,vis[maxn];
LL ans = 0,a[maxn],sum[maxn],ma[maxn],ml[maxn],mr[maxn],t[maxn],l[maxn],r[maxn];

vector <int> v[maxn],v1[maxn];

void dfs(int x)
{
	for (int i = 0; i < v1[x].size(); i++) {
		int to = v1[x][i];
		if (vis[to]) continue;
		vis[to] = 1;
		v[x].push_back(to);
		dfs(to);
	}
}

void solve(int k)
{
	int siz = v[k].size();
	if (!siz) {
		sum[k] = ma[k] = t[k] = a[k];
		return;
	}
	
	LL m1,m2,M1,M2;
	m1 = m2 = M1 = M2 = 0;
	for (int i = 0; i < siz; i++) {
		int to = v[k][i];
		solve(to);
		if (ma[to] > M1) {
			M2 = M1; M1 = ma[to]; 
		}
		else if (ma[to] > M2) M2 = ma[to];
		if (sum[to] > m1) { 
			m2 = m1; m1 = sum[to];
		}
		else if (sum[to] > m2) m2 = sum[to];
		ma[k] = max(ma[k],ma[to]);
		t[k] = max(t[k],t[to] + a[k]);
	}
	ma[k] = max(ma[k],a[k]+m1+m2);
	sum[k] = m1+a[k];
	for (int i = 0; i < siz; i++) 
		l[i+1] = r[i+1] = sum[v[k][i]];
	l[0] = r[siz+1] = ml[0] = mr[siz+1] = 0;
	
	ans = max(ans,1LL*M1+1LL*M2);
	for (int i = 1; i <= siz; i++) {
		if (l[i] > l[i-1]) ml[i] = l[i-1];
		else if (l[i] > ml[i-1]) {
			ml[i] = l[i]; l[i] = l[i-1];
		}
		else l[i] = l[i-1],ml[i] = ml[i-1];
	}
	for (int i = siz; i; i--) {
		if (r[i] > r[i+1]) mr[i] = r[i+1];
		else if (r[i] > mr[i+1]) {
			mr[i] = r[i]; r[i] = r[i+1];
		}
		else r[i] = r[i+1],mr[i] = mr[i+1];
	}
	
	for (int i = 0; i < siz; i++) {
		LL now[4];
		int ch = v[k][i];
		now[0] = l[i]; now[1] = ml[i];
		now[2] = r[i+2]; now[3] = mr[i+2];
		sort(now,now+4);
		ans = max(ans,a[k] + now[2] + now[3] + ma[ch]);
		ans = max(ans,t[ch] + now[3] + a[k]);
		t[k] = max(t[k],ma[ch] + now[3] + a[k]);
	}
}

int main()
{
	#ifdef YZY
		freopen("yzy.txt","r",stdin);
	#endif
	
	cin >> n;
	for (int i = 1; i <= n; i++) scanf("%I64d",&a[i]);
	for (int i = 1; i < n; i++) {
		int x,y; scanf("%d%d",&x,&y);
		v1[x].push_back(y);
		v1[y].push_back(x);
	}
	
	vis[1] = 1; dfs(1);
	solve(1);
	cout << ans;
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值