链接:https://www.nowcoder.com/acm/contest/116/A
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
输入描述:
Input consists of a single line containing a string made up of the letters N, S, E, and W representing the route to transmit to the rover. The maximum length of the string is 100.
输出描述:
Display the minimum number of characters needed to encode the route.
示例1
输入
WNEENWEENEENE
输出
10
分析: n, 这么小,暴力就行
代码
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = (int) 500 + 11;
const int M = (int) 1e6 + 11;
const int inf = 0x3f3f3f3f;
int solve(string s, string t){
int cnt = 0; int len =s.size();
int pos;
while((pos = s.find(t)) < s.size()){
cnt ++;
s = s.substr(pos + t.size(), s.size());
}
if(cnt <= 1) return len; // 注意这里 必须要重复 即 至少出现两次
else return len - t.size() * cnt + t.size() + cnt;
}
int main(){
string s, t;
while(cin >> s){
int len = s.size();
int mx = inf;
for(int i = 0; s[i]; i++){
t = "";
for(int j = i; s[j]; j++){
t += s[j];
mx = min(mx, solve(s, t));
}
}
printf("%d\n", mx);
}
return 0;
}
链接:https://www.nowcoder.com/acm/contest/116/B
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
杨老师给同学们玩个游戏,要求使用乘法和减法来表示一个数,他给大家9张卡片,然后报出一个数字,要求大家用表达式的形式来表示出这个数
100 可以表示为这样的形式:100 = 129*67-8543 , 还可以表示为:100 = 13*489-6257
注意特征:表达式中,数字1~9分别出现且只出现一次(不包含0)。
类似这样的表达式,100 有 20 种表示法。
题目要求:
从标准输入读入一个正整数N(N<1000 * 1000)
程序输出该数字用数码1~9不重复不遗漏地组成的全部种数。
注意:不要求输出每个表示,只统计有多少表示法!
输入描述:
一个正整数N
输出描述:
输出有多少种表示法
示例1
输入
100
输出
20
备注:
注意只有一个乘法和一个减法,*号保证在-的前面
分析: 暴力枚举就行了。
代码
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
string s = "123456789";
int Judge(int a, int b, int n){
ll x = 0; ll y = 0; ll z = 0;
for(int i = 0; i < a; i++) x = x * 10 + s[i] - '0';
for(int i = a; i < b; i++) y = y * 10 + s[i] - '0';
for(int i = b; i < 9; i++) z = z * 10 + s[i] -'0';
return (x * y - z) == n ;
}
int main(){
int n; scanf("%d", &n);
int cnt = 0;
do{
for(int i = 1; i < 8; i++){
for(int j = i + 1; j < 9; j++) {
cnt += Judge(i, j, n);
}
}
}
while(next_permutation(s.begin(), s.end())) ;
printf("%d\n", cnt);
return 0;
}
链接:https://www.nowcoder.com/acm/contest/116/C
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
杨老师认为他的学习能力曲线是一个拱形。勤奋的他根据时间的先后顺序罗列了一个学习清单,共有n个知识点。但是清单中的知识并不是一定要学习的,可以在不改变先后顺序的情况下有选择的进行学习,而每一个知识点都对应一个难度值。杨老师希望,后学习的知识点的难度一定不低于前一个知识点的难度(i < j 时ai<=aj),而可能存在一个临界点,在临界点以后,他希望后学习的知识点的难度一定不高于前一个知识点的难度( i < j时ai>=aj)。杨老师想尽可能多的学习知识。请问:杨老师最多可以学习多少知识?
输入描述:
第一行:一个整数n(0 < n < 500000)接下来一行:n个整数,第i个整数ai(0<=ai<500000)表示第i道题目的难度。
输出描述:
一行一个整数,表示杨老师最多可以学习多少个知识。
示例1
输入
5
1 4 2 5 1
输出
4
分析: 两遍 LIS 就行了 ,然后枚举 间断的那个位置 ,取最多就行。
代码
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = (int) 500000 + 11;
const int M = (int) 1e6 + 11;
int a[N + 1];
int dp[N + 1];
int dp1[N + 1], dp2[N + 1];
int main(){
int n; scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
int len = 1; dp[len] = a[1];
dp1[1] = 1;
for(int i = 2; i <= n; i++) {
if(a[i] >= dp[len]) dp[++len] = a[i];
else
dp[upper_bound(dp, dp+ len , a[i]) - dp] = a[i];
dp1[i] = len;
}
reverse(a + 1, a + 1 + n);
//for(int i = 1; i <= n; i++) printf("%d ", dp1[i]); puts("");
len = 1; dp[len] = a[1];
dp2[1] = 1;
for(int i = 2; i <= n; i++) {
if(a[i] >= dp[len]) dp[++len] = a[i];
else
dp[upper_bound(dp, dp + len, a[i]) - dp] = a[i];
dp2[i] = len;
}
//for(int i = 1; i <= n; i++) printf("%d ", dp2[i]);
int ans = 0;
for(int i = 1; i <= n; i++){
ans = max(ans, dp1[i] + dp2[n - i]);
}
printf("%d\n", ans);
return 0;
}
D 勤奋的杨老师(二)
链接:https://www.nowcoder.com/acm/contest/116/D
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
众所周知,杨老师是一位十分勤奋的老师,他非常的热爱学习。
勤奋的他为自己罗列了一个学习清单,共有n个知识点,他可以有选择的进行学习。
每个知识点都会对应0个或1个或多个先修知识点(只有学会了先修知识点才能学习该知识点),同时每个知识点都有一个智慧值和一个智力消耗值。
杨老师希望在进行过激烈的学习之后,他的收获可以·量化为所有学过的题的智慧值的和与智力消耗值的和的差值。请问,这个值最大是多少?
输入描述:
第一行:一个整数n(n<=500)接下来n行,每行两个整数,代表第i个知识点的智慧值和智力消耗值接下来若干行,每行2个整数u, v,代表u是v的先修知识点。
输出描述:
一行,表示杨老师的收获的最大值
示例1
输入
4
5 1
2 1
1 2
1 2
3 1
2 4
2 1
输出
4
分析: 最大权闭合图的裸题
代码
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = (int) 500 + 11;
const int M = (int) 1e6 + 11;
const ll inf = 0x3f3f3f3f3f3f3f3f;
struct Edge {
int form,to; ll cap,flow; int nexts;
Edge() {}
Edge(int _form, int _to, ll _cap, ll _flow, int _nexts){
form = _form; to = _to; cap = _cap; flow = _flow; nexts = _nexts;
}
}edge[M];
int head[N],top;
void init(){
memset(head,-1,sizeof(head));
top=0;
}
void addedge(int a,int b,ll c){
edge[top]=Edge(a, b, c, 0, head[a]);
head[a] = top++;
edge[top]=Edge(b, a, 0, 0, head[b]);
head[b]=top++;
}
int vis[N],dis[N];
int cur[N];
bool bfs(int st,int ed){
queue<int>Q;
memset(vis,0,sizeof(vis));
memset(dis,-1,sizeof(dis));
Q.push(st);vis[st]=1;dis[st]=1;
while(!Q.empty()){
int now=Q.front();Q.pop();
for(int i=head[now];i!=-1;i=edge[i].nexts){
Edge e=edge[i];
if(!vis[e.to]&&e.cap-e.flow>0){
vis[e.to]=1;
dis[e.to]=dis[now]+1;
if(e.to==ed) return 1;
Q.push(e.to);
}
}
}
return 0;
}
ll dfs(int now,ll a,int ed){
if(a==0||now==ed) return a;
ll flow=0,f;
for(int &i=cur[now];i!=-1;i=edge[i].nexts){
Edge &e=edge[i];
if(dis[e.to]==dis[now]+1&&(f=dfs(e.to,min(e.cap-e.flow,a),ed))>0){
e.flow+=f;
flow+=f;
edge[i^1].flow-=f;
a-=f;
if(a==0) break;
}
}
return flow;
}
ll max_flow(int st ,int ed){
ll flow=0;
while(bfs(st,ed)){
memcpy(cur,head,sizeof(head));
flow+=dfs(st,inf,ed);
}
return flow;
}
int main(){
init();
int n; scanf("%d", &n);
int S = 0, T = n + 1;
ll ans = 0; ll a, b;
for(int i = 1; i <= n; i++){
scanf("%lld%lld", &a, &b);
if(a >= b) {
ans += a - b;
addedge(S, i, a - b);
}else {
addedge(i, T, b - a);
}
}
while(scanf("%d%d", &a, &b) != EOF) addedge(b, a, inf);
printf("%lld\n", ans - max_flow(S, T));
return 0;
}
链接:https://www.nowcoder.com/acm/contest/116/F
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
我们知道有一种神奇的排序方法叫做猴子排序,就是把待排序的数字写在卡片上,然后让猴子把卡片扔在空中,等落下的时候观察这些卡片是否从左到右已经排序完成(我们认为不会发生卡片落地后叠在一起的情况)如果有序则排序完成,否则让猴子再扔一遍,直到卡片有序,那么问题来了,给你N个卡片,每个卡片上写着一个大写字母,请问猴子第一次扔这些卡片就按字典序排序完成的概率有多大?
输入描述:
第一行是一个整数N(1 < N < 100)表示给猴子N张卡片,接下来是一个长度为N的字符串,代表这些卡片上所写的字母。
输出描述:
输出一行,表示猴子排序第一次就成功的概率(用分子为1的分数表示)。
示例1
输入
7
SCIENCE
输出
1/1260
分析: 我们只要求出 用所给字符随意排列可以构成多少种不同的排列不就行了
高中学过。
代码
import java.io.*;
import java.util.*;
import java.math.*;
public class Main {
public static final int N = 100 + 11;
public static BigInteger[] fac = new BigInteger[N + 1];
public static int[] cnt = new int[N];
public static void init(){
fac[0] = new BigInteger("1"); int j = 1;
for(BigInteger i = new BigInteger("1"); j < N; i = i.add(new BigInteger("1") ), j++) {
fac[j] = fac[j - 1].multiply(i);
}
}
public static void main (String[] args) {
init();
Scanner cin = new Scanner (System.in);
int n = cin.nextInt();
String str = cin.next();
for(int i = 0; i < str.length(); i++) {
// System.out.println(str.charAt(i));
cnt [(str.charAt(i) - 'A')] ++;
}
BigInteger ans = fac[n];
//System.out.println(ans);
for(int i = 0; i < 26; i++){
ans = ans.divide(fac[cnt[i]]);
}
System.out.println("1/"+ans);
}
}
链接:https://www.nowcoder.com/acm/contest/116/J
来源:牛客网
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
Recently, researchers on Mars have discovered N powerful atoms. All of them are different. These atoms have some properties. When two of these atoms collide, one of them disappears and a lot of power is produced. Researchers know the way every two atoms perform when collided and the power every two atoms can produce.
You are to write a program to make it most powerful, which means that the sum of power produced during all the collides is maximal.
输入描述:
There are multiplecases. The first line of each case has an integer N (2 <= N <= 10), whichmeans there are N atoms: A1, A2, … , AN.Then N lines follow. There are N integers in each line. The j-th integer on thei-th line is the power produced when Ai and Aj collidewith Aj gone. All integers are positive and not larger than 10000.
The last case isfollowed by a 0 in one line.
There will be no morethan 500 cases including no more than 50 large cases that N is 10.
输出描述:
Output the maximalpower these N atoms can produce in a line for each case.
示例1
输入
2
0 4
1 0
3
0 20 1
12 0 1
1 10 0
0
输出
4
22
分析: 从结果上看,最后一定是有一个消失的顺序 使其最后的值最大。我们可以暴力枚举这个顺序,然后 再求出当前顺序下可以得到的最大权值,最后再取最大。那么给定固定的顺序,怎么求最大权值呢,只要提前预处理好 第i个点在所有状态下的最大值就好,详细的看代码吧。
代码
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = (int) 500 + 11;
const int M = (int) 1e6 + 11;
const ll inf = 0x3f3f3f3f3f3f3f3f;
int n;
int mp[11][11]; int a[11];
int dp[11][1 << 11]; // dp[i][j]表示 第i个原子在j状态下爆破i的最大值
void init(){ // 预处理 dp
for(int i = 0; i < n; i++){
for(int j = 0; j < (1 << n) - 1; j++){
int mx = 0;
for(int k = 0; k < n; k++){
if(((j >> k) & 1) && k != i)
mx = max(mx, mp[k][i]);
}
dp[i][j] = mx;
}
}
}
int solve(){
int ans = 0; int state = (1 << n) - 1;
for(int i = 0; i < n - 1; i++){
state ^= (1 << a[i]);
ans += dp[a[i]][state];
}
return ans;
}
int main(){
while(scanf("%d", &n) && n ){
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
scanf("%d", &mp[i][j]);
}
}
init();
for(int i = 0; i < 11; i++) a[i] = i;
int ans = 0;
do{
ans = max(ans, solve());
}while(next_permutation(a, a + n)) ;
printf("%d\n", ans);
}
return 0;
}