Timus 2011. Long Statement 排列组合的运用

Nikita, a schoolboy, is currently taking part in one of programming contests. He is really upset because all the problem statements are so long and unclear. So he took the statement of the first problem
and cut it into pieces in such a way that each piece contained exactly one letter. After that, he threw away all pieces with letter other than “a”, “b” or “c”. Now he has only npieces and wants to compile from them his own statement that should be
shorter and clearer than the original one.

The new statement should be a single word compiled from all n letters placed in some order. Nikita wondered if he can compile at least six different words of length n from the letters.
If this is not true, he will be ruined and will start solving other problems. Help Nikita to answer this monumental question!

Input

The first line contains an integer n that is the number of pieces with letters (1 ≤ n ≤ 100). The second line describes these pieces as n integers from 1 to 3. 1 represents
a piece with letter “a”, 2 represents a piece with letter “b”, 3 represents a piece with letter “c”.

Output

If Nikita can compile at least six different words of length n, output “Yes”. Otherwise output “No”.

Sample

input output
6
1 2 2 3 3 3
Yes

本题我使用了permutation的知识去解决。

就是把 1 2 2 3 3 3 看着是一个排列,然后求6次下一个排列,如果无重复,那么就是Yes,如果有重复,那么就是No了。

求排序的时间效率是O(n),所以本算法的速度还是相当快的。

能够运用上学过的知识,感觉真是太好了。

#include <string>
#include <vector>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;

bool permuteLongStatement(vector<int> &rs, vector<int> &tmp)
{
	int i = tmp.size() - 2;
	for ( ; i >= 0 && tmp[i] >= tmp[i+1]; i--);
	if (i < 0)
	{
		reverse(tmp.begin(), tmp.end());
		return tmp != rs;
	}
	int j = tmp.size() - 1;
	for ( ; tmp[j] <= tmp[i]; j--);
	swap(tmp[i], tmp[j]);
	reverse(tmp.begin()+i+1, tmp.end());
	return tmp != rs;
}

void LongStatement2011()
{
	int n;
	cin>>n;
	vector<int> rs(n);
	for (int i = 0; i < n; i++)
	{
		cin>>rs[i];
	}
	vector<int> tmp(rs);
	bool ok = true;
	for (int i = 0; i < 5; i++)//注意这里是5不是6,因为第一个不permute前算一个
	{
		if (!permuteLongStatement(rs, tmp))
		{
			ok = false;
			break;
		}
	}
	if (ok) cout<<"Yes";
	else cout<<"No";
}
时间: 2024-10-12 09:11:20

Timus 2011. Long Statement 排列组合的运用的相关文章

HDU--5396(区间dp+排列组合)

做这道题的时候,想到会不会是dp,然后发现dp可做,但是一直被自己坑到死. 枚举最后合并的那个位置,然后对于加减号的,分成的前后两个部分都有不同的组合方法, (a1+a2........) +  (b1,b2.............)         对于每个a,被加b的个数的阶乘次 ,对于每个b,被加a的个数的阶乘次 减法同理 乘法特殊一点 (a1+a2........) *  (b1,b2.............)  乘法分配率,直接将两部分的总和相乘即可 想到这些还远远没有结束,因为最

排列组合

(常考)错位排列 有N封信和N个信封,每封信都不装在自己信封里的排列种数记作Dn,则 D1=0,D2=1,D3=2,D4=9,D5=44,D6=265 一.相邻问题---捆绑法 不邻问题---插空法 对于某几个元素不相邻的排列问题,可先将其他元素排好,再将不相邻元素在已排好的元素之间及两端空隙中插入即可. [例题1]一张节目表上原有3个节目,如果保持这3个节目的相对顺序不变,再添进去2个新节目,有多少种安排方法? A.20 B.12 C.6 D.4 [答案]A. [解析] 以下内容需要回复才能看

hdu 1799 (循环多少次?)(排列组合公式)

循环多少次? Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3051    Accepted Submission(s): 1117 Problem Description 我们知道,在编程中,我们时常需要考虑到时间复杂度,特别是对于循环的部分.例如, 如果代码中出现 for(i=1;i<=n;i++) OP ; 那么做了n次OP运算

排列组合问题

一.不同元素子集问题 78. Subsets Given a set of distinct integers, nums, return all possible subsets. 给定一组非重复数字,求出所有可能的子集 解析: 例如 [1,2,3],解法: 首先放[],然后往已有的[]中放1 1. 首先放1 此时已有[ [], 1 ] 2. 然后对[ [], 1 ] 放2 于是此时有 [ [], [1], [2], [1,2] ] 3. 然后对[ [], [1], [2], [1,2] ]

排列组合问题之圆形分布

1.问题1.1 团团坐有一张圆桌,坐了A,B,C,D四个人,已知,D在A的右边,C在D的对面,请问A,B,C,D,的坐次? 解答:这个问题相对简单,我们纸上画一画,就能画出他们的可能的位置了 但是,可能还有一种解,比如我们把A,B,C,D依次右转一个位,也是满足条件的,而且只要保持他们的相对位置不变,依次右转n个位都是问题的解,而且还有个有趣的事情,当他们转了一圈(即右转4个位)后,他们右回到原位了 2.圆形分布上面这个问题就是一种圆形分布,那么他和直线分布的区别在哪里呢?又有什么联系呢?上面文

【noi 2.6_9288】&amp;【hdu 1133】Buy the Ticket(DP / 排列组合 Catalan+高精度)

题意:有m个人有一张50元的纸币,n个人有一张100元的纸币.他们要在一个原始存金为0元的售票处买一张50元的票,问一共有几种方案数. 解法:(学习了他人的推导后~) 1.Catalan数的应用7的变形.(推荐阅读:http://www.cnblogs.com/chenhuan001/p/5157133.html).P.S.不知我之前自己推出的公式“C(n,m)*C(2*m,m)/(m+1)*P(n,n)*P(m,m)”是否是正确的. (1)在不考虑m人和n人本身组内的排列时,总方案数为C(m+

用递归写排列组合问题

最近递归弄的人头疼,但是这两天看过来也稍微总结了一些不能称得上是技巧的技巧吧 问题如下,将1,2,3,4这四个数字排列组合的输出来,看网上有个很二的方法吧,就是将10000以内的数全部输出再筛选,对此有点无语,但是程序倒是挺好编的,嘿嘿 回归到正题中,用递归的思想解决 (1)采用旋转数字的方法,当步长为1时,1234还是1234,步长为2的时候,1234可以变为1243.1324...,步长为3 的时候,1234可以变为1423,诸如此类,最重要的能体现递归的就是将每次递归一次的数字还可以接着旋

LightOJ1005 Rooks(DP/排列组合)

题目是在n*n的棋盘上放k个车使其不互相攻击的方案数. 首先可以明确的是n*n最多只能合法地放n个车,即每一行都指派一个列去放车. dp[i][j]表示棋盘前i行总共放了j个车的方案数 dp[0][0]=1 转移就是从第i-1行转移到第i行,对于第i行要嘛放上一个车要嘛不放,放的话有n-j-1种方法.即dp[i][j]=dp[i-1][j]+dp[i-1][j-1]*(n-j-1). 1 #include<cstdio> 2 #include<cstring> 3 using na

Codeforces Gym 100187D D. Holidays 排列组合

D. Holidays Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100187/problem/D Description Everyone knows that the battle of Endor is just a myth fabled by George Lucas for promotion of his movie. Actually, no battle of Endor has