<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: rgb(255, 255, 255);">第一场</span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: rgb(255, 255, 255);">第一场</span>
A.回文串
1000ms / 65536KB / C, C++ or JAVA
Author: dovegx / Editor: dovegx
Description
据说字符串都是很难的,可是芳姐最喜欢了,最近他迷上了回文字符串,回文串正着读和反着读是一样的,比如 abba, aaaa都是回文串, abbc不是回文串。芳姐想知道如果把整个字符串拆散重新组合,能组成的最长的回文串。原串字母不一定全部用上。
Input Description
多样例(大约10个),每个样例一行仅有小写字母组成的字符串,字符创长度不大于100000
Output Description
每个样例输出一个整数,表示能组成的最长回文串的长度
Sample Input
abab
abc
Sample Output
4
1
开一个数组a[26]保存字母的个数,每两个字母构成前后的回文,最后判断是否存在多出一个字母放置在回文数列的最中间
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <set>
#include <ctime>
#include <queue>
#include <numeric>
#include <list>
#pragma warning (default : 4996)
using namespace std;
#define eps 1e-8
#define LL long long
#define ULL unsigned longlong
#define mod 1000000007
#define MP make_pair
int a[26];
char s[100010];
int main()
{
while (gets(s))
{
memset(a, 0, sizeof(a));
int ans = 0;
int len = strlen(s);
for (int i = 0; i < len; i++) {
a[s[i] - 'a']++;
}
for (int i = 0; i < 26; i++) {
while (a[i] >= 2) {a[i] -= 2; ans += 2; }
}
for (int i = 0; i < 26; i++) {
if (a[i] == 1) {ans++; break; }
}
printf("%d\n", ans);
}
return 0;
}
B.Combination
1000ms / 65536KB / C, C++ or JAVA
Author: / Editor: dovegx
Description
Ilya plays a card game by the following rules.
A player has several cards. Each card contains twononnegative integers inscribed, one at the top of the card and one at thebottom. At the beginning of the round the player chooses one of his cards toplay it. If the top of the card contains number ai, and the bottom containsnumber bi, then when the player is playing the card, he gets ai points and alsogets the opportunity to play additional bi cards. After the playing the card isdiscarded.
More formally: let's say that there is a counter ofthe cards that can be played. At the beginning of the round the counter equalsone. When a card is played, the counter decreases by one for the played cardand increases by the number bi, which is written at the bottom of the card.Then the played card is discarded. If after that the counter is not equal tozero, the player gets the opportunity to play another card from the remainingcards. The round ends when the counter reaches zero or the player runs out ofcards.
Of course, Ilya wants to get as many points aspossible. Can you determine the maximum number of points he can score providedthat you know his cards?
Input Description
Thefirst line contains a single integer n( 1<=n<=1000) — the number of cardsIlya has.
Each of the next n lines contains two non-negative space-separated integers — ai and bi( 0 <= ai, bi <= 10^4 )— thenumbers, written at the top and the bottom of the i-th card correspondingly.
Output Description
Printthe single number — the maximum number of points you can score in one round by thedescribed rules.
Sample Input
2
1 0
2 0
3
1 0
2 0
0 2
Sample Output
2
3
贪心,先取bi最大的,以此来增加取卡片的次数。如果有多个相同的bi,选择ai最大的,以此来最大化分数。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#pragma warning (default : 4996)
using namespace std;
struct cards {
int a, b;
bool operator < (constcards &oth)const {
return b > oth.b || (b == oth.b && a > oth.a);
}
}c[1005];
int main()
{
int n;
while (scanf("%d", &n) == 1)
{
for (int i = 0; i < n; i++) {
scanf("%d%d", &c[i].a,&c[i].b);
}
sort(c, c + n);
int couter = 1, cnt = 0, ans = 0;
while (couter > 0 && cnt < n) {
ans += c[cnt].a;
couter--;
couter += c[cnt++].b;
}
printf("%d\n", ans);
}
return 0;
}
C.单峰排序
1000ms / 65536KB / C, C++ or JAVA
Editor: dovegx
Description
一个n的全排列A[i]是单峰的,当且仅当存在某个x使得A[1]<A[2]<...<A[x]>A[x+1]>...>A[n]。
例如,对于9的全排列,125798643是一个单峰排列,123456789也是一个单峰排列,但356298741就不是。
试求n的单峰全排列的个数。
Input Description
输入一个数n。n小于max_int64
Output Description
输出n的全排列中单峰排列的个数。
由于这个数可能很大,因此你只需要输出它mod 1234567的值。
Sample Input
3
Sample Output
4
经过少量演算,得到的规律是 ans[n] = 2^(n-1),因为n<max_int64,考虑到要用快速幂.
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <set>
#include <ctime>
#include <queue>
#include <numeric>
#include <list>
#pragma warning (default : 4996)
using namespace std;
#define eps 1e-8
#define LL long long
#define ULL unsigned longlong
#define mod 1000000007
#define MP make_pair
#define mod1 1234567
LL ans, n;
LL qm(LLx) {
LL r = 1, base = 2;
while (x != 0) {
if (x % 2 == 1) r = r * base %mod1;
base = base * base % mod1;
x >>= 1;
}
return r;
}
int main()
{
while (scanf("%lld", &n) == 1)
{
ans = qm(n - 1);
printf("%lld\n", ans); //华工是用lld读long long ,卡了好久=。=。
}
return 0;
}
D.Escape
3000ms / 65536KB / C, C++ or JAVA
Editor: dovegx
Description
After the battleagianst BOSS smallMing,dovegx finds the island start sinking into sea at aconstant speed(1 unit per minute).surely,dovegx has to run,run and run,untilreaching his boat at the coast.
The island is described as a matrix of n*m grids,each has a height.At any timea grid with height h<0 must be filled with water.At the beginning,dovegxstays at grid (1,1),also the top left corner of the island,and the boatis(n,m).Assume dovegx now locates at (i,j) he can move to(i+1,j),(i-1,j),(i,j+1)or(i,j-1) at next minute if no water there,also he canstay still.(note,the sea around the island has many many water..)
Input Description
Thereare multiple cases.
The first line of the input contains n,m.(1<=n,m<=1000).Next n lines eachcontain m integers.aij is the height of grid(i,j).(-10000<=aij<=10000).It´s guaranteed,a11>=0.
Output Description
Tellif dovegx can escape from the island,print "Yes"and the minimalminutes he need to reach his boat(arrive at grid(n,m)) if he can.print only"No" if he cannot.
Sample Input
2 2
1 1
1 2
3 3
1 2 3
1 2 3
1 2 3
Sample Output
Yes
2
No
广搜,妈蛋,卡MLE和WA好久。。原来是标记入队顺序的问题;
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#pragma warning (default : 4996)
using namespace std;
int dis[4][2] = { 1, 0,-1, 0, 0, 1, 0, -1 };
struct T {
int val;
int pre;
}a[1005][1005];
struct point {
int x, y;
};
bool vis[1005][1005];
int n, m;
queue<point> que;
bool bfs()
{
point init;
init.x = 1; init.y = 1;
que.push(init); // 标记(1,1)入队。
vis[1][1] = true;
a[1][1].pre = 0;
while (!que.empty()) {
point loc = que.front(); que.pop();
if (loc.x == n && loc.y == m)returntrue; //找到了就结束。
for (int i = 0; i < 4; i++) {
point nstat;
nstat.x = loc.x + dis[i][0];
nstat.y = loc.y + dis[i][1];
a[nstat.x][nstat.y].pre =a[loc.x][loc.y].pre + 1; // pre是标记第几步到达nstat;
//下面判断是否合法,合法就入队。
if(!vis[nstat.x][nstat.y] && (a[nstat.x][nstat.y].val -a[nstat.x][nstat.y].pre) >= 0 && nstat.x <= n && nstat.y<= m && nstat.x >= 1 && nstat.y >= 1) {
que.push(nstat);
vis[nstat.x][nstat.y] = true;//标记nstat入队
}
}
}
return false;
}
int main()
{
while (scanf("%d%d", &n, &m) == 2) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m;j++) {
scanf("%d", &a[i][j].val);
}
}
memset(vis, 0, sizeof(vis));
while (!que.empty()) que.pop();//多数据处理,要初始化队列。
if (bfs()) {
printf("Yes\n%d\n", a[n][m].pre);
}
else printf("No\n");
}
return 0;
}
E.CutString
2000ms / 65536KB / C, C++ or JAVA
Editor: dovegx
Description
Given a strings, partition s such that every substring of the partition is a palindrome.
Find the minimum cuts needed for a palindrome partitioning of s.
For example, given s = "aab",
Output 1 since the palindrome partitioning ["aa","b"] couldbe produced using 1 cut.
Input Description
Inputcontains multiple test cases.
For each you are given a string s which length is less than 300 and onlycontains lowercases.
Output Description
Foreach output the minimum cuts needed for a palindrome partitioning of s.*//*/
Sample Input
aab
a
abacdcefe
Sample Output
1
0
2
题意:是给定一个字符串S,问你最少cut多少次,才能使得cut出来的子串都是回文串
题解:首先是扫描所有是回文串的子串,将他们存入一个vector里面,然后扫描这个vector,
如果其中两个在本来的串S中是连续的,就连接一条权为1的边;如果是起点子串,就和超级源点(编号为0)连一条权为0的边;如果是终点子串,就和超级终点(编号为vector.size()+1)连一条权为0的边。所以问题就转变成求这个图的最短路。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <set>
#include <ctime>
#include <queue>
#include <numeric>
#include <list>
#include <functional>
using namespace std;
#define eps 1e-8
#define LL long long
#define ULL unsigned long long
#define mod 1000000007
#define MP make_pair
#define PII pair<int,int>
#define INF 0x3f3f3f3f
struct Node{
string str;
int id,from, to; // id是赋予每个子串编号,from是起始位置,to是终止位置;
Node(){}
Node(string s, inti, int from, intto){
str = s;
id = i;
this->from= from;
this->to= to;
}
};
const int mxn =305*305;
int first[mxn], nxt[mxn], vv[mxn], cost[mxn], e;
int d[mxn], vis[mxn];
void add(int u,int v,int c) //加边函数;
{
vv[e] = v; cost[e] = c; nxt[e] =first[u];
first[u] = e++;
}
vector<Node>ivec;
void dij() // 优先队列优化的dijkstra
{
priority_queue<PII, vector<PII>,greater<PII> > q;
memset(vis, 0, sizeof(vis));
for (int i = 0; i <= ivec.size()+1; ++i) d[i] = (i == 0? 0 : INF);
q.push(MP(d[0],0));
while(!q.empty())
{
PII u = q.top(); q.pop();
intx = u.second;
if(vis[x])continue;
vis[x] = true;
for(int i = first[x]; i != -1; i = nxt[i])
{
inty = vv[i];
if(d[y]> d[x] + cost[i])
{
d[y] = d[x] +cost[i];
q.push(MP(d[y], y));
}
}
}
}
int main()
{
string in;
while(cin>> in)
{
ivec.clear();
e = 0;
int id = 0;
memset(first, -1, sizeof(first)); // 这几步都是初始化操作
intn = in.length();
for(int i = 0; i < n; ++i) //扫描所有子串
{
for(int j =0; i - j >= 0 && i + j < n; ++j)
{
if (in[i-j] != in[i+j])break;
else
{
ivec.push_back(Node(in.substr(i-j,i+j+1), ++id, i-j, i+j)); // 保存回文子串信息
}
}
for(int j =0; i - j >= 0 && i + j + 1 < n; ++j)
{
if (in[i-j] != in[i+j + 1])break;
else
{
ivec.push_back(Node(in.substr(i-j,i+j+2), ++id, i-j, i+j+1)); // 保存回文子串信息
}
}
}
for(int i = 0; i < ivec.size(); ++i)
{
if(ivec[i].from == 0) add(0, ivec[i].id, 0); //超级源点
if(ivec[i].to == n - 1) add(ivec[i].id, ivec.size() + 1, 0); // 超级终点
for(int j = 0; j < ivec.size(); ++j)
{
if (ivec[i].to + 1 == ivec[j].from)
{
add(ivec[i].id,ivec[j].id, 1);
}
}
}
dij();
printf("%d\n",d[ivec.size()+1]);
}
return 0;
}
G.蜡烛是我的!
1000ms / 65536KB / C, C++ or JAVA
Editor: dovegx
Description
小明玩炉石传说中毒过深,以至于某天晚上大叫一声“蜡烛是我的!”。。现在有k根蜡烛,每根蜡烛在燃烧之后都会剩下一个蜡烛头。已知每m个蜡烛头又可以合成一个新的蜡烛,现在我给你k和m,请你帮我算算这k根蜡烛最多能提供多久的光明?(每根蜡烛可以燃烧一小时)
Input Description
第一行有一个正整数T,表示样例数(T<=100)
对于每一个case,有2个正整数,k和m (k<=1000,1<m<=100)
Output Description
对于每一个case,输出一行,即最大照明时间
Sample Input
1
4 2
Sample Output
7
水的一笔。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <set>
#include <ctime>
#include <queue>
#include <numeric>
#include <list>
#pragma warning (default : 4996)
using namespace std;
#define eps 1e-8
#define LL long long
#define ULL unsigned longlong
#define mod 1000000007
#define MP make_pair
int main()
{
int t;
int k, m;
int ans;
int left;
scanf("%d", &t);
while (t--) {
scanf("%d%d", &k, &m);
ans = left = k;
while (left >= m) {
left -= m - 1;
ans++;
}
printf("%d\n", ans);
}
return 0;
}
H.解方程
1000ms / 65536KB / C, C++ or JAVA
Editor: dovegx
Description
解方程 x1+x2+x3+x4+….+xn=m. m是常数,xi是未知数,求这个方程有多少组非负解。
Input Description
多样例,
每个样例是一个方程,方程之间没有空格或者其他无关符号,具体格式看样例输入
未知数最多100个,m的值不超过100。
Output Description
因为答案会很大,输出结果模 10007
Sample Input
x1+x2=3
Sample Output
4
Hint
(0, 3 ), (3, 0),(1,2),(2,1)
题解: 什么鸡鸡隔板法的,我也不知道,一直调都没过。。。
J.序列操作
1000ms / 65536KB / C, C++ or JAVA
Editor: dovegx
Description
已知一个初始为0的序列长度为n,进行m组操作,每次操作将as……at增加k。
Input Description
第一行输入T表示有T个样例
每个样例第一行n, m( 0<n, m<=1000000)
接下来m行 s, t, k, 表示将as……at增加k。
Output Description
每个样例输出最终数列的和
Sample Input
2
3 2
1 1 1
1 3 1
2 1
1 2 1
Sample Output
4
2
你这么水,你爹地妈咪知道吗?
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <set>
#include <ctime>
#include <queue>
#include <numeric>
#include <list>
#pragma warning (default : 4996)
using namespace std;
#define eps 1e-8
#define LL long long
#define ULL unsigned longlong
#define mod 1000000007
#define MP make_pair
int main()
{
int T, n, m;
LL s, t, k;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &m);
LL sum = 0;
while (m--) {
scanf("%lld%lld%lld", &s, &t,&k);
sum += (t - s + 1) * k;
}
printf("%lld\n", sum);
}
return 0;
}
I.集合
1000ms / 65536KB / C, C++ or JAVA
Editor: dovegx
Description
在一个神秘领土里有N个城市,城市之间有道路相连,一共有M条道路。领土里面的城市分为两个帮派,黑派或者红派。有关部门说两个派必定会一起混乱,所以两个派就干起来了。他们首先集合人员,战斗之前黑派的人不能走到红派的城市,反之也不能。整个领土里的人尽可能地集合在一起。问最大的集合有多少人。
Input Description
多样例
第一行 N, M ( 0 < N <= 100, 0 < M < 5000 ).
接下来N行 xi, yi. xi = 0表示城市i为红派,x=1城市i为黑派,yi表示城市i的人口;
接下来M行 u, v 表示城市u和城市v相连,城市序号从1开始
Output Description
最大的集合人数
Sample Input
6 10
1 67
0 0
1 24
0 58
0 64
1 45
2 4
2 6
2 3
4 1
4 1
3 4
5 5
4 3
3 6
6 1
Sample Output
136
额,这是传说中的并查集。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#pragma warning (default : 4996)
using namespace std;
int pa[101];
int findset(inta) {
return pa[a] !=a ? pa[a] = findset(pa[a]) :a;
}
int main()
{
int n, m;
int x[101], y[101];
int xx, yy;
bool vis[101];
while (scanf("%d%d", &n, &m) == 2) {
memset(vis, 0, sizeof(vis));
for (int i = 1; i <= n; i++) {
pa[i] = i;
}
for (int i = 1; i <= n; i++) {
scanf("%d%d", &x[i],&y[i]);
}
for (int i = 1; i <= m; i++) {
scanf("%d%d", &xx, &yy);
if (x[xx] == x[yy])pa[findset(xx)] = findset(yy);//刚开始写pa[xx] = yy跪了。合并根节点。
}
int ans = -1;
for (int i = 1; i <= n; i++) {
if (vis[i] == true) continue;
int sum = y[i];
for (int j = i + 1; j <=n; j++) {
if (x[i] != x[j]) continue;
else
{
vis[j] = 1;
if (findset(i) ==findset(j))
sum += y[j];
}
}
ans = max(sum, ans);
}
cout << ans << endl;
}
return 0;
}
其实也可以用深搜做, 两个城市阵营相同且相通的就连一条边。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <set>
#include <ctime>
#include <queue>
#include <numeric>
#include <list>
#include <functional>
using namespace std;
#define eps 1e-8
#define LL long long
#define ULL unsigned long long
#define mod 1000000007
#define MP make_pair
#define PII pair<int,int>
#define INF 0x3f3f3f3f
#define mxn 105
vector<int> G[mxn]; //邻接表保存边
struct Node{
int x; //阵营
int y; //人口
void in()
{
scanf("%d%d",&x, &y);
}
}p[mxn];
int vis[mxn]; //深搜标记数组
int sum; //保存每次搜索的结果
int ans;
void dfs(int u)
{
vis[u] = 1; //标记已访问
sum += p[u].y; // 加入当前节点人口
int d =G[u].size();
for (int i = 0; i < d; ++i) //枚举遍历所有(u,v)边
{
intv = G[u][i];
if(!vis[v])dfs(v);
}
}
void init() //初始化操作
{
memset(vis, 0, sizeof(vis));
for (int i = 0; i < mxn; ++i) G[i].clear();
ans = 0;
}
void add(int u,int v) //加入边,因为是无向边,所以要加入两次。
{
G[u].push_back(v);
G[v].push_back(u);
}
int main()
{
int n, m;
int u, v;
while(~scanf("%d%d", &n, &m))
{
init();
for(int i = 1; i <= n; ++i) p[i].in();
for(int i = 1; i <= m; ++i)
{
scanf("%d%d", &u, &v);
if(p[u].x == p[v].x) //两个城市阵营相同且相通的就连一条边。
add(u, v);
}
for(int i = 1; i <= n; ++i) //遍历搜索
{
if(!vis[i])
{
sum = 0;
dfs(i);
if(sum > ans) ans = sum;
}
}
printf("%d\n",ans);
}
return 0;
}