今日日常训练四题 20190409 暴力专题

首先,我想说今天的题目都让我觉得好感动,至少都有一点思路,差不多可以做出来了,很开心,昨天的题目是真的恶心。

然后开始记录打卡啦!!!

D. Too Easy Problems

You are preparing for an exam on scheduling theory. The exam will last for exactly T milliseconds and will consist of n problems. You can either solve problem i in exactly ti milliseconds or ignore it and spend no time. You don't need time to rest after solving a problem, either.

Unfortunately, your teacher considers some of the problems too easy for you. Thus, he assigned an integer ai to every problem i meaning that the problem i can bring you a point to the final score only in case you have solved no more than ai problems overall (including problem i).

Formally, suppose you solve problems p1, p2, ..., pk during the exam. Then, your final score s will be equal to the number of values of jbetween 1 and k such that k ≤ apj.

You have guessed that the real first problem of the exam is already in front of you. Therefore, you want to choose a set of problems to solve during the exam maximizing your final score in advance. Don't forget that the exam is limited in time, and you must have enough time to solve all chosen problems. If there exist different sets of problems leading to the maximum final score, any of them will do.

Input

The first line contains two integers n and T (1 ≤ n ≤ 2·105; 1 ≤ T ≤ 109) — the number of problems in the exam and the length of the exam in milliseconds, respectively.

Each of the next n lines contains two integers ai and ti (1 ≤ ai ≤ n1 ≤ ti ≤ 104). The problems are numbered from 1 to n.

Output

In the first line, output a single integer s — your maximum possible final score.

In the second line, output a single integer k (0 ≤ k ≤ n) — the number of problems you should solve.

In the third line, output k distinct integers p1, p2, ..., pk (1 ≤ pi ≤ n) — the indexes of problems you should solve, in any order.

If there are several optimal sets of problems, you may output any of them.

Examples
input
Copy
5 300
3 100
4 150
4 80
2 90
2 300
output
Copy
2
3
3 1 4
input
Copy
2 100
1 787
2 788
output
Copy
0
0

input
Copy
2 100
2 42
2 58
output
Copy
2
2
1 2
Note

In the first example, you should solve problems 3, 1, and 4. In this case you'll spend 80 + 100 + 90 = 270 milliseconds, falling within the length of the exam, 300 milliseconds (and even leaving yourself 30 milliseconds to have a rest). Problems 3 and 1 will bring you a point each, while problem 4 won't. You'll score two points.

In the second example, the length of the exam is catastrophically not enough to solve even a single problem.

In the third example, you have just enough time to solve both problems in 42 + 58 = 100 milliseconds and hand your solutions to the teacher with a smile.

 

 

这个是一个贪心的题目,果然贪心千变万化,有点难啊,不过呢,这个比之前我写的好多了。
有点思路,但是还是不会写。
这个题目应该是对时间进行贪心,然后再满足时间的条件下,用优先队列来维护答案,
这就可以既满足时间的要求,又满足了对分数的要求。

 我现阶段的对贪心的认识就是,一般比较简单的贪心都只要对一个进行贪心就可以了,

然后稍微进阶一点的就是这种,对两个进行贪心,而且还有一点点的冲突,需要好好处理。

然后更加恶心的就是昨天那种,不过昨天的可以不用贪心写。

 

 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cstring>
#include <iostream>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 100;
struct node
{
	int id, goal, time;
	friend bool operator<(const node&a,const node &b)
	{
		if (a.goal == b.goal) return a.time < b.time;
		return a.goal > b.goal;
	}
}exa[maxn];
priority_queue<node>que;
bool cmp(node a,node b)
{
	if (a.time == b.time) return a.goal > b.goal;
	return a.time < b.time;
}
int main()
{
	ll ans = 0;
	int n, t;
	cin >> n >> t;
	for(int i=1;i<=n;i++)
	{
		cin >> exa[i].goal >> exa[i].time;
		exa[i].id = i;
	}
	sort(exa + 1, exa + 1 + n, cmp);
	for(int i=1;i<=n;i++)
	{
		if (exa[i].time > t) break;
		if(exa[i].time<=t)
		{
			t -= exa[i].time;
			ans++;
			que.push(exa[i]);
		}
		while(!que.empty()&&que.top().goal<ans)
		{
			t += que.top().time;
			ans--;
			que.pop();
		}
	}
	printf("%lld\n", ans);
	printf("%d\n", que.size());
	while(!que.empty())
	{
		printf("%d ", que.top().id);
		que.pop();
	}
	printf("\n");
	return 0;
}

  

 

time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

There are nn distinct points on a coordinate line, the coordinate of ii-th point equals to xixi. Choose a subset of the given set of points such that the distance between each pair of points in a subset is an integral power of two. It is necessary to consider each pair of points, not only adjacent. Note that any subset containing one element satisfies the condition above. Among all these subsets, choose a subset with maximum possible size.

In other words, you have to choose the maximum possible number of points xi1,xi2,,ximxi1,xi2,…,xim such that for each pair xijxij, xikxik it is true that |xijxik|=2d|xij−xik|=2d where dd is some non-negative integer number (not necessarily the same for each pair of points).

Input

The first line contains one integer nn (1n21051≤n≤2⋅105) — the number of points.

The second line contains nn pairwise distinct integers x1,x2,,xnx1,x2,…,xn (109xi109−109≤xi≤109) — the coordinates of points.

Output

In the first line print mm — the maximum possible number of points in a subset that satisfies the conditions described above.

In the second line print mm integers — the coordinates of points in the subset you have chosen.

If there are multiple answers, print any of them.

Examples
input
Copy
6
3 5 4 7 10 12
output
Copy
3
7 3 5
input
Copy
5
-1 2 5 8 11
output
Copy
1
8
Note

In the first example the answer is [7,3,5][7,3,5]. Note, that |73|=4=22|7−3|=4=22, |75|=2=21|7−5|=2=21 and |35|=2=21|3−5|=2=21. You can't find a subset having more points satisfying the required property.

 

 

这个题目,很明显是一个找规律的题目,我也发现了,但是可惜,并没有完全找到,然后搜了一下题解,

你会发现这个最多就是三个,最少就是一个(这个不要找规律,看清楚题目,或者WA几发就发现了) 

这个 最多就是三个的规律,你可以自己推一下,很简单

就是对 x,x+2^d,x+2^d1 这个是三个的,然后你就会发现就是这个三个进行排列x在中间,然后还有就是d1和d相差一个1,自己手动推一下吧。

如果是四个,你会发现无法满足。

知道这个就很好做了。 用map存数进去,再枚举2的幂,到30就好了,然后再枚举每一个数是不是有可能满足。

 

 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cstring>
#include <map>
#include <iostream>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 100;
map<ll, int>mp;
ll a[maxn];
ll p[maxn];

void pow()
{
	for(int i=0;i<=30;i++)
	{
		p[i] = 1;
		for(int j=1;j<=i;j++)
		{
			p[i] *= 2;
		}
		//printf("p[%d]=%lld\n", i, p[i]);
	}
}

int main()
{
	int n;
	cin >> n;
	mp.clear();
	for(int i=1;i<=n;i++)
	{
		ll x;
		cin >> x;
		a[i] = x;
		mp[x] = 1;
	}
	pow();
	sort(a + 1, a + 1 + n);
	int flag=0, mark=0,num=0,m=0,fl=0;
	for(int i=0;i<=30;i++)
	{
		flag = 0;
		for(int j=1;j<=n;j++)
		{
			//printf("%d %d %lld %lld %d\n",i, j, a[j], a[j] + p[i],mp[a[j]+p[i]]);
			flag = 0;
			//printf("qqq\n");
			if(mp[a[j]+p[i]]==1&&a[j]!=a[j]+p[i])
			{
				m = i;
				num = j;
			}
			if (mp[a[j] + p[i]] == 1 && mp[a[j] + p[i + 1]] == 1)
			{
				if (a[j] == a[j] + p[i] || a[j] == a[j] + p[i + 1] || a[j] + p[i] == a[j] + p[i + 1]) continue;
				mark = i;
				flag = j;
				break;
			}
		}
		if (flag) break;
	}
	if(flag)
	{
		printf("3\n");
		printf("%lld %lld %lld\n", a[flag], a[flag] + p[mark], a[flag] + p[mark + 1]);
	}
	else if(num)
	{
		printf("2\n");
		printf("%lld %lld\n", a[num], a[num] + p[m]);
	}
	else 
	{
		printf("1\n");
		printf("%lld\n", a[1]);
	}
//	else printf("0\n");
	return 0;
}

  

 

 

 

time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Professor GukiZ doesn't accept string as they are. He likes to swap some letters in string to obtain a new one.

GukiZ has strings ab, and c. He wants to obtain string k by swapping some letters in a, so that k should contain as many non-overlapping substrings equal either to b or c as possible. Substring of string x is a string formed by consecutive segment of characters from x. Two substrings of string x overlap if there is position i in string x occupied by both of them.

GukiZ was disappointed because none of his students managed to solve the problem. Can you help them and find one of possible strings k?

Input

The first line contains string a, the second line contains string b, and the third line contains string c (1 ≤ |a|, |b|, |c| ≤ 105, where |s| denotes the length of string s).

All three strings consist only of lowercase English letters.

It is possible that b and c coincide.

Output

Find one of possible strings k, as described in the problem statement. If there are multiple possible answers, print any of them.

Examples
input
Copy
aaa
a
b
output
Copy
aaa
input
Copy
pozdravstaklenidodiri
niste
dobri
output
Copy
nisteaadddiiklooprrvz
input
Copy
abbbaaccca
ab
aca
output
Copy
ababacabcc
Note

In the third sample, this optimal solutions has three non-overlaping substrings equal to either b or c on positions 1 – 2 (ab), 3 – 4 (ab), 5 – 7 (aca). In this sample, there exist many other optimal solutions, one of them would be acaababbcc.

 

 

 

 

这个题目,我想法就想错了,我开始以为是贪心,后来发现并不是,这个不是的反例我也是看别人的博客的。

其实呢,你仔细看看这个数据范围,应该就可以发现了,应该不是贪心,一般贪心的数据范围有点大,无法枚举。

而且这个题目用贪心你自己不觉得有点小慌吗?反正我当时用就挺慌的,感觉不太对。

这个可以直接暴力枚举,因为这个只有1e5,所以你可以枚举B或者C字符串的数量,这个你不要觉得困难,

困难的话,你用贪心先写一次,然后再来看,你会发现很简单的。

对于枚举B,C有两种,一种就是每个都枚举一次,看哪个更好,

还有就是只枚举数量更多的那个,这个是因为如果你枚举数量小的话,如果出现numb=0,numc!=0那你就凉凉了,

接下来就是看代码的时候了/

 

 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cstring>
#include <map>
#include <string>
#include <iostream>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 100;
string s, a, b;
int vis[30], bis[maxn];
int via[30], vib[30];
int main()
{
	int numa = inf, numb = inf;
	int otha = inf, othb = inf;
	cin >> s >> a >> b;
	int len = s.size();
	int lena = a.size();
	int lenb = b.size();
	memset(vis, 0, sizeof(vis));
	memset(via, 0, sizeof(via));
	memset(vib, 0, sizeof(vib));
	for (int i = 0; i < len; i++) vis[s[i] - 'a']++;
	for (int i = 0; i < lena; i++) via[a[i] - 'a']++;
	for (int i = 0; i < lenb; i++) vib[b[i] - 'a']++;
	for (int i = 0; i <= 26; i++)
	{
		if (via[i] == 0) continue;
		numa = min(numa, vis[i] / via[i]);
	}
	for (int i = 0; i <= 26; i++)
	{
		if (vib[i] == 0) continue;
		numb = min(numb, vis[i] / vib[i]);
	}
//	printf("%d %d\n", numa, numb);
	int ans = 0, mark = 0;
	if(numa>numb)
	{
		for(int i=1;i<=numa;i++)
		{
			for (int j = 0; j < 26; j++) bis[j] = vis[j];
			for(int j=0;j<26;j++)
			{
				bis[j] -= via[j] * i;
			}
			//求在枚举a的状态下,b的最多的数。
			for(int j=0;j<26;j++)
			{
				if (vib[j] == 0) continue;
				otha = min(otha, bis[j] / vib[j]);
			}
			if(i+otha>ans)
			{
				ans = i + otha;
				mark = i;
			}
		}
	}
	else
	{
		for(int i=1;i<=numb;i++)
		{
		//	printf("i=%d\n", i);
			for (int j = 0; j < 26; j++) bis[j] = vis[j];
			for(int j=0;j<26;j++)
			{
				bis[j] -= vib[j] * i;
				//printf("bis[%d]=%d\n", j, bis[j]);
			}
			// 在枚举b的情况下,求a得到的最多的子串数
			for(int j=0;j<26;j++)
			{
				if (via[j] == 0) continue;
				othb = min(othb, bis[j] / via[j]);
				//printf("othb=%d \n", othb);
			}
			if(othb+i>ans)
			{
				ans = othb + i;
				mark = othb;
				//printf("ans=%d mark=%d\n", ans, mark);
			}
		}
	}
	//printf("%d %d\n", mark, ans);
	for (int i = 0; i < mark; i++) cout << a;
	for (int i = 0; i < ans - mark; i++) cout << b;
	for(int i=0;i<26;i++)
	{
		vis[i] = vis[i] - via[i] * mark - vib[i] * (ans - mark);
		if (vis[i] <= 0) continue;
		for (int j = 0; j < vis[i]; j++) printf("%c", 'a' + i);
	}
	printf("\n");
	return 0;
}

  

 

 

 

time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

The start of the new academic year brought about the problem of accommodation students into dormitories. One of such dormitories has a a × b square meter wonder room. The caretaker wants to accommodate exactly n students there. But the law says that there must be at least 6 square meters per student in a room (that is, the room for n students must have the area of at least 6n square meters). The caretaker can enlarge any (possibly both) side of the room by an arbitrary positive integer of meters. Help him change the room so as all nstudents could live in it and the total area of the room was as small as possible.

Input

The first line contains three space-separated integers na and b (1 ≤ n, a, b ≤ 109) — the number of students and the sizes of the room.

Output

Print three integers sa1 and b(a ≤ a1; b ≤ b1) — the final area of the room and its sizes. If there are multiple optimal solutions, print any of them.

Examples
input
Copy
3 3 5
output
Copy
18
3 6
input
Copy
2 4 4
output
Copy
16
4 4

 

 

 

 

这个题目1800的分数,我觉得也太不应该了,这个题目虽然不说是傻逼题,不过真的不难。

开始以为是二分,后来发现不需要用二分写。。。。

不过。。。我T了,然后还不知道怎么优化。。。。?

后来看了题解,发现离A就差一两步。。。?

这个主要就是给你一个数字n,还有a,b让你求a1,b1

要求就是a1*b1>=6*n

这个可以直接暴力就可以了,暴力到根号下6*n,就好了

不过开始我因为我直接开根号然后+1不对,其实还需要再加1,这个我一个一个查出来的。。。

 

 

 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstring>
#include <map>
#include <string>
#include <iostream>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 100;

int main()
{
	ll n, a, b, x = 0, y = 0;
	cin >> n >> a >> b;
	if (a > b) swap(a, b);
	if (a*b > 6 * n)
	{
		printf("%lld\n", a*b);
		printf("%lld %lld\n", a, b);
		return 0;
	}
	ll len = sqrt(6 * n) + 1;
	for (int i = a; i <= len; i++)
	{
		//printf("i=%d\n", i);
		if (6*n%i == 0 && 6*n / i >= b)
		{
			
			x = i;
			y = 6*n / i;
			break;
		}
		if (i*b > 6*n)
		{
			x = i;
			y = b;
			break;
		}
	}
	printf("%lld\n", x*y);
	printf("%lld %lld\n", x, y);
	return 0;
}

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/EchoZQN/p/10678994.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值