偶数加成记
时间限制: 2000ms 内存限制: 256M
描述
xyb这里有n个整数。xyb想要得到这n个整数最大的偶数和(即该和为偶数),每个整数最多只能加一次。请你计算出最大的这个值。
输入
输入包含多组。输入的第一个数为一个n(1<=n<=100000)。下一行包括xyb的n个整数,以空格隔开。每个整数的范围为1~10^9。
输出
请输出最大的偶数和。
样例输入1 复制
3
1 2 3
样例输出1
6
样例输入2 复制
5
999999999 999999999 999999999 999999999999999999
样例输出2
3999999996
解题思路:
偶数全部加起来,看奇数多少个,如果是奇数个那么把最小的那个剔除,如果偶数个则全部相加。
AC代码:
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <set>
#include <deque>
#include <functional>
#define maxn 100100
#define INF 0x3f3f3f3f
#define N 1010
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
ll a[maxn];
int main()
{
int n;
while (~scanf("%d", &n))
{
ll sum = 0;
int cnt = 0;
for (int i = 1; i <=n; i++)
{
ll x;
scanf("%lld", &x);
if (x & 1)
a[cnt++]= x;
else sum += x;
}
sort(a, a + cnt, greater<ll>());
if (cnt & 1)
{
for (int i = 0; i <cnt - 1; i++)
sum +=a[i];
}
else
{
for (int i = 0; i <cnt; i++)
sum +=a[i];
}
printf("%lld\n", sum);
}
return 0;
}
理智逃税
时间限制: 2000ms 内存限制: 256M
描述
xyb在一个高大上的国家工作,这个国家有一个特殊的税收政策。若xyb每年的收入为n元(n>=2),那么xyb所要交的税为n的所有约数中的最大值(不包括n本身。)比如,如果xyb一年收入为6元,那么他就需要交税3元;如果xyb一年收入为25元,那么他就需要交税5元;如果xyb一年收入为2元,那么他就需要交税1元。
然而xyb是个机(jiao)智(hua)的人,他想要上交的税越少越好。所以,他决定,将每年的收入n元,拆分一下:n1+n2+...+nk=n(这里的k表示拆分的份数,k=1也是可以的),然后再将每份所要交的税一起上交即可。当然,对于每份的钱数来说,不能少于2元(如果某一份少于2元他就会被正直的人给揭发了!)
xyb想知道他最少只需要交多少钱的税,你快来帮帮他吧!
输入
输入第一行包含一个整数n(2<=n<=2*10^9),表示xyb的总钱数。
输出
输出一个整数,表示xyb最少需要交多少税。
样例输入1 复制
4
样例输出1
2
样例输入2 复制
27
样例输出2
3
解题思路:
基于哥德巴赫猜想。“对于偶数:一个大于2的偶数可以分为两个质数的和;对于奇数:一个奇数n且不为质数,若其n-2为质数,那么n可以分为两个质数的和,若n-2不为质数,那么n可以分为三个质数的和。”
AC代码:
#include<cstdio>
#include<iostream>
using namespace std;
bool isprime(int n)
{
for (int i = 2; i*i<=n; i++)
if (n%i == 0)
return false;
return true;
}
int main()
{
int n;
while (cin >> n)
{
if (isprime(n))
{
printf("1\n");
continue;
}
if (n % 2 == 0 || isprime(n - 2))
{
printf("2\n");
continue;
}
printf("3\n");
}
return 0;
}
我要吃粽子
时间限制: 1000ms 内存限制: 128M
描述
快看!高空中漂浮着好多粽子,而且越高的粽子越大!
好神奇,我要吃到最大的粽子!
地上零零散散放着K种砖块(这些砖块能帮我们吃到高处的粽子)。对于第i类砖块的描述:
1. 第i类砖块,每块高度皆为H。
2. 第i类砖块共有Q个。
3. 第i类砖块,凡是放到高于L的高空会自动消失。
用这些砖块一块块堆砌,以此爬向天空。为了使吃到的粽子尽可能大,问我最高能爬到多高的高空?
输入
有多组数据
每组输入,第一行为一个整数K(1 <= K <= 400)。
第二行为k+1行,每行三个空格分隔的整数H(1 <= H <= 100),L (1 <= L <= 40000),Q(1 <= Q<= 10),表示第i种砖块的H,L,Q。
输出
每组输出一个整数h,表示能吃到的最大粽子所在高度。
样例输入1 复制
3
7 40 3
5 23 8
2 52 6
样例输出1
48
解题思路:
考虑多重背包,不同的是:每次放一个砖要考虑下面又没有东西,不能放在空中
所以先要根据最高度,排序。然后用多重背包递推求解。递推公式:
dp[i][j]=dp[i][j-h[i]] 和 used[i][j]=used[i][j-h[i]]+1 (其中i表示第i种砖块,j表示高度转移,再用used记录一下第i种砖块用的个数)
AC代码:
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define maxn 40010
#define lson root << 1
#define rson root << 1 | 1
#define lent (t[root].r -t[root].l + 1)
#define lenl (t[lson].r - t[lson].l + 1)
#define lenr (t[rson].r - t[rson].l + 1)
#define N 404
#define eps 1e-6
#define pi acos(-1.0)
#define e exp(1.0)
using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;
typedef unsigned long longull;
int dp[maxn], used[maxn];
struct node
{
int h, l, q;
friend bool operator< (node a,node b)
{
return a.l < b.l;
}
} p[N];
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r", stdin);
freopen("out.txt","w", stdout);
long _begin_time = clock();
#endif
int k;
while (~scanf("%d", &k))
{
for (int i = 0; i <k; i++)
scanf("%d%d%d", &p[i].h, &p[i].l, &p[i].q);
sort(p, p + k);
memset(dp, 0, sizeof(dp));
dp[0] = 1;
for (int i = 0; i <k; i++)
{
memset(used, 0,sizeof(used));
for (int j = p[i].h; j <= p[i].l; j++)
{
if (used[j - p[i].h] < p[i].q)
{
if (!dp[j]&& dp[j - p[i].h])
{
dp[j]= dp[j - p[i].h];
used[j]= used[j - p[i].h] + 1;
}
}
}
}
int ans = 0;
for (int i =maxn; i >= 0;i--)
if (dp[i])
{
ans =i;
break;
}
printf("%d\n", ans);
}
#ifndef ONLINE_JUDGE
long _end_time = clock();
printf("time =%ld ms.", _end_time -_begin_time);
#endif
return 0;
}
Universe7去约会
时间限制: 1000ms 内存限制: 128M
描述
Universe7有个非常漂亮的女朋友,他每天都要和她去约会(嫌虐狗?上周末干啥去了!)。他的女友为了考验他,每次都选一个非常神奇的迷宫等他。在迷宫里有许多只蜗牛,如果踩到了蜗牛就会暴毙而亡。但蜗牛会在隔一定的时间消失一秒。其余的时间蜗牛就会待在那里等待大傻子去踩。
下面给出迷宫的地图图例。'.'代表可以走的路,'#'代表蜗牛,'U'代表Universe7的位置,'G'代表他女朋友的位置。每一秒钟,Universe7都可以向上向下向左向右移动一格。
输入
第一行给出样例的总数T(0<T<20),接下来有T个样例。每个样例给出迷宫的行数r列数c和蜗牛消失的间隔时间k(1<=r,c<=100,2<=k<=10)。接下来的r行代表迷宫的地图。
输出
如果Universe7可以成功约会,输出最短时间,否则输出"Please give me another chance!".
样例输入1 复制
2
6 6 2
...U..
...#..
.#....
...#..
...#..
..#G#.
4 4 2
U###
####
####
###G
样例输出1
7
Please give me another chance!
解题思路:
带时间状态的广搜,考虑开三层vis[x][y][z]其中前两层表示坐标,第三层表示时间状态,当t%k==0则表示可进状态。
AC代码:
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define maxn 100010
#define lson root << 1
#define rson root << 1 | 1
#define lent (t[root].r -t[root].l + 1)
#define lenl (t[lson].r - t[lson].l + 1)
#define lenr (t[rson].r - t[rson].l + 1)
#define N 1111
#define eps 1e-6
#define pi acos(-1.0)
#define e exp(1.0)
using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;
typedef unsigned long longull;
char mp[110][110];
bool vis[110][110][11];
int dir[4][2] = { { 1, 0 },{ -1, 0 },{ 0, -1 },{0, 1 } };
int r, c, k, ans;
struct node
{
int x, y, t;
node(int a, int b, int c) { x =a; y = b; t = c; }
};
void bfs(int stax,int stay)
{
memset(vis, 0, sizeof(vis));
queue<node> q;
q.push(node(stax,stay, 0));
vis[stax][stay][0] = 1;
while (!q.empty())
{
node cur = q.front();
q.pop();
if (mp[cur.x][cur.y] =='G')
{
ans = cur.t;
return;
}
for (int i = 0; i <4; i++)
{
int dx = cur.x + dir[i][0];
int dy = cur.y + dir[i][1];
int time = cur.t + 1;
if (dx >= 0&& dx < r && dy >= 0 && dy < c &&(mp[dx][dy] !='#' || time % k == 0) &&!vis[dx][dy][time % k])
{
vis[dx][dy][time% k] = 1;
q.push(node(dx, dy, time));
}
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r", stdin);
freopen("out.txt","w", stdout);
long _begin_time = clock();
#endif
int t;
scanf("%d", &t);
while (t--)
{
scanf("%d%d%d", &r,&c, &k);
int stax, stay;
bool flag = 0;
for (int i = 0; i <r; i++)
{
scanf("%s", mp[i]);
for (int j = 0; j < c&& !flag; j++)
if (mp[i][j] == 'U')
{
stax= i;
stay= j;
flag= 1;
break;
}
}
ans = INF;
bfs(stax, stay);
if (ans < INF)
printf("%d\n", ans);
else
puts("Pleasegive me another chance!");
}
#ifndef ONLINE_JUDGE
long _end_time = clock();
printf("time =%ld ms.", _end_time -_begin_time);
#endif
return 0;
}
读书好多读书读好书
时间限制: 2000ms 内存限制: 256M
描述
xyb刚度过一段繁忙的时期,终于有空闲的时间来读(wan)书(shua)了。今天,他有t分钟的空闲时间来读书。因此,他跑到了图书馆开始他的读书大计。图书馆中有n本书,编号从1~n,xyb读完每本书所花的时间为ai分钟。
xyb决定从随机的一本书开始读,然后一本接一本的读下去。比如,假设xyb决定从第i本书开始读,那么他的读书顺序编号就是i+1,i+2...如果他把自己的空闲时间花光了,那他就不会再读下去了。所以,xyb想请你帮他确定一下读的第一本书的编号,使得他所能读完的书的本数最大(若最后一本书他读不完,则这本书不能算进去),输出他所能读的书本数的最大值。
输入
第一行包含两个整数n,t(1<=n<=10^5,1<=t<=10^9)——n表示图书馆的书本数,t表示xyb的空闲时间(分钟)。
第二行包含n个整数a1,a2,...,an(1<=ai<=10^4),ai表示xyb读完第i本书所需时间(分钟)。
输出
输出一个整数,表示xyb所能读的书本数的最大值。
样例输入1 复制
4 5
3 1 2 1
样例输出1
3
样例输入2 复制
3 3
2 2 3
样例输出2
1
解题思路:用数组存下前缀和,然后遍历过程中,二分往前找。
AC代码:
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <set>
#include <deque>
#include <functional>
#define maxn 100100
#define INF 0x3f3f3f3f
#define N 1010
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
ll a[maxn];
ll sum[maxn];
int main()
{
int n, t;
while (~scanf("%d%d", &n,&t))
{
sum[0] = 0;
memset(a, 0, sizeof a);
for (int i = 1; i <=n; i++)
{
scanf("%lld", &a[i]);
sum[i] =sum[i - 1] + a[i];
}
int ans = 0;
for (int i = 1; i <=n; i++)
{
ll res = sum[i] -t;
if (res <= 0)
ans =i;
else
{
int l = 0, r = i;
while (l <= r)
{
int mid = l + r>> 1;
if (sum[mid] >=res)
{
ans= max(ans, i - mid);
r= mid - 1;
}
else l = mid + 1;
}
}
}
printf("%d\n", ans);
}
return 0;
}
寻找flash
时间限制: 1000ms 内存限制: 128M
描述
众所周知,flash学长很喜欢玩游戏。今天,他想和大家玩一个捉迷藏的游戏。flash学长会藏在一个矩阵中并且可以使自己名字中的任意字母大写,现在看聪明的你能不能找到flash了。
(在这个矩阵中,如果将字母横着,竖着或者斜着连在一起能组成flash的任意组合便认为是找到了flash)
输入
输入有多组。每组第一个行为两个整数数n,m(n,m<=10),代表矩阵有n行m列。接下来是一个n*m大小的矩阵。
输出
如果flash藏在这个矩阵中,输出yes,否则输出no。
样例输入1 复制
2 5
FeeSh
alabb
1 5
falsh
样例输出1
yes
no
解题思路:
因为n和m很小,直接搜一下就行,dfs或者bfs
AC代码:
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <set>
#include <deque>
#include <functional>
#define maxn 100100
#define INF 0x3f3f3f3f
#define N 1010
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
char mp[20][20];
bool vis[20][20];
int dir[8][2] = { { 1, 0 },{ 0, 1 },{ -1, 0 },{0, -1 },{ -1, -1 },{ -1, 1 },{ 1, -1 },{ 1, 1 } };
int n, m, flag;
struct node
{
int x, y, state;
node(int a, int b, int c) {
x = a;
y = b;
state = c;
}
};
bool judge(int x, int y,int state)
{
if (state == 2)
return mp[x][y] == 'L' || mp[x][y] == 'l';
else if (state == 3)
return mp[x][y] == 'A' || mp[x][y] == 'a';
else if (state == 4)
return mp[x][y] == 'S' || mp[x][y] == 's';
return mp[x][y] == 'H' || mp[x][y] == 'h';
}
void bfs(int sx, int sy)
{
memset(vis, 0, sizeof(vis));
queue<node> q;
q.push(node(sx, sy, 1));
while (!q.empty())
{
node cur = q.front();
q.pop();
if (cur.state == 5)
{
flag = 1;
return;
}
vis[cur.x][cur.y] = 1;
for (int i = 0; i <8; i++)
{
int dx = cur.x + dir[i][0];
int dy = cur.y + dir[i][1];
int state = cur.state + 1;
if (dx >= 0&& dy >= 0 && dx < n && dy < m &&!vis[dx][dy])
{
if (judge(dx, dy, state))
q.push(node(dx, dy, state));
}
}
}
}
int main()
{
while (~scanf("%d%d", &n,&m))
{
memset(mp, 0, sizeof(mp));
for (int i = 0; i <n; i++)
scanf("%s", mp[i]);
flag = 0;
for (int i = 0; i < n&& !flag; i++)
for (int j = 0; j < m&& !flag; j++)
if (mp[i][j] == 'F' || mp[i][j] == 'f')
bfs(i, j);
if (flag)
puts("yes");
else
puts("no");
}
return 0;
}
知山知水,树木树人
时间限制: 1000ms 内存限制: 256M
描述
作为一名北林学子,知山知水,树木树人的校训肯定是牢记心中的。xyb也牢记这点。现在,他就在研究k叉树的问题。
对于k叉树,xyb给出了他自己的定义:
1.每个节点(除叶子节点外)都有k个子节点;
2.每条边都具有权值,每个节点下的第i条边的权值为i;
例如,如果是一棵3叉树:
此刻,xyb提出了一个有趣的问题:“从根节点出发,有多少条路径的权值和(即这条路径上所有的权值加起来)是等于n的,且这些路径还要满足一个条件,即经过的所有边,至少有一条边的权值是大于等于d的。”
现在这个问题交给你来解决吧,由于路径数可能会非常大,输出时请对1000000007 (10^9+7)取模。(即%1000000007)
输入
输入为一行。包括三个整数n,k,d(1<=n,k<=100;1<=d<=k),用空格隔开。
输出
输出为一行。即满足条件的路径数对1000000007取模的结果。
样例输入1 复制
3 3 2
样例输出1
3
样例输入2 复制
3 3 3
样例输出2
1
样例输入3 复制
4 3 2
样例输出3
6
样例输入4 复制
4 5 2
样例输出4
7
解题思路:
dp[i][j],i存到和,j==0时,表示到i为止,还没出现过>=d的数,反之,j==1时,则出现过。
然后每层dp一下,状态转移为:
if(j>=d)
dp[i][1]=(dp[i][1]+dp[i-j][0]+dp[i-j][1])%mod
else
dp[i][0]=(dp[i][0]+dp[i-j][0])%mod
dp[i][1]=(dp[i][1]+dp[i-j][1])%mod
AC代码:
#include <bits/stdc++.h>
#define maxn 100100
#define INF 0x3f3f3f3f
#define N 1010
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
ll dp[110][2];
int main()
{
int n, k, d;
while (~scanf("%d%d%d%d", &n,&k, &d))
{
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
for (int i = 1; i <=n; i++)
{
for (int j = 1; j <=min(k, i); j++)
{
if (j >= d)
dp[i][1]= (dp[i][1] + dp[i - j][0] + dp[i - j][1]) % mod;
else
{
dp[i][1]= (dp[i][1] + dp[i - j][1]) % mod;
dp[i][0]= (dp[i][0] + dp[i - j][0]) % mod;
}
}
}
cout << dp[n][1] % mod << endl;
}
return 0;
}