今天是院ACM新生赛的决赛啦, 题目出的比较难, 最多为9道
可以看到大部分还是WA一片
下面是题解, 有两道题太过简单 只提供了思路.
A 外币兑换
//签到题, 从下面几个中选一个最大的, 相乘保留两位小数就行了
B polygon
//其实就是求多边形的内角和公式, 即使忘了应该想一下也就能推出来180*(n-2)
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<stdlib.h>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
usingnamespacestd;
#definems(x,n)memset(x,n,sizeof(x));
typedef long long LL;
const LL maxn=1e6+10;
int main()
{
LL n;
while(scanf("%lld",&n)!=EOF){
printf("%lld\n",(n-2)*180);
}
return 0;
}
C 赌气球
//完全根据来题意模拟就好了, 两个细节注意一下, 有有可能玩不够k次游戏就结束啦, 游戏结束前也要先输出Not enough token.
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <cmath>
#include <map>
using namespace std;
#define ms(x, n) memset(x,n,sizeof(x));
typedef long long LL;
const LL maxn = 1e6+10;
int T, k, n1, b, t, n2;
int solve()
{
if(t > T)
return -1;
else if(n1 < n2){
if(b == 1){
T+=t;
return 1;
}
else if(b == 0){
T-=t;
T = max(0, T);
return 0;
}
}
else if(n1 > n2){
if(b == 0){
T+=t;
return 1;
}
else if(b == 1){
T-=t;
return 0;
}
}
}
int main()
{
cin >> T >> k;
while(k--){
cin >> n1 >> b >> t >> n2;
int flag = solve();
if(flag == -1)
printf("Not enough tokens. Total = %d.\n",T);
else if(flag == 1)
printf("Win %d! Total = %d.\n",t,T);
else if(flag == 0)
printf("Lose %d. Total = %d.\n",t,T);
if(T <= 0){
printf("Game Over.\n");
break;
}
}
return 0;
}
D 胡辣汤店
//斐波那契数列, 记得用long long
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
#define ms(x,n)memset(x,n,sizeof(x));
typedef long long LL;
const LL maxn=85;
int from,to;
LL cusNum[maxn];
void init()
{
ms(cusNum,0);
cusNum[1]=1,cusNum[2]=1;
for(int i=3;i<=maxn;i++)
cusNum[i]=cusNum[i-1]+cusNum[i-2];
}
int main()
{
init();
while(cin>>from>>to){
LL sum=0;
for(int i=from;i<=to;i++)
sum+=cusNum[i];
cout<<sum<<endl;
}
return 0;
}
E 害死人不偿命的猜想
//数据量不大, 直接用递归算法处理一下即可, 终止条件是n==1, 判读奇偶对应处理即可
F 奖学金
//这道题是一道贪心算法的最基础的题目, 贪心算法很好理解, 就算每次都处理最优解, 最终结果就一定是最优解, 这道题目就算每次都取最大能取的面额, 直到为0
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
#define ms(x,n)memset(x,n,sizeof(x));
typedef long long LL;
const LL maxn=85;
int money[]={1,5,10,20,50,100};
int main()
{
int n,cont=0;
cin>>n;
while(n>0){
for(int i=5;i>=0;i--)
if(n>=money[i]){
cont+=(n/money[i]);
n%=money[i];
}
}
cout<<cont<<endl;
}
G筛法
//这道题用到了筛法求素数(getPrime()函数), 而且要把素数提前预处完毕, 不能说用到一次再处理一次, 先测试一下可知n为104时最大取104729内的素数, 然后就求出104729以内的所有素数就好了, 之后遍历循环输出即可
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;
#define ms(x, n) memset(x,n,sizeof(x));
typedef long long LL;
const LL maxn = 104729;
bool isPrime[maxn];
int primeNum[maxn];
void getPrime()
{
ms(primeNum, 0);
for(int i = 2; i <= maxn; i++)
if(!isPrime[i])
for(int j = 2; i*j <= maxn; j++)
isPrime[i*j] = 1;
int tag = 1;
for(int i = 2; i <= maxn; i++)
if(!isPrime[i])
primeNum[tag++] = i;
}
int main()
{
getPrime();
int m, n;
cin >> m >> n;
int tag = 0; //是否是第一个数
for(int i = primeNum[m]; i <= primeNum[n]; i++){
if(!isPrime[i]){
if(tag==0) printf("%d",i), tag++;
else printf(" %d",i), tag++;
if(tag==10)
printf("\n"), tag = 0;
}
}
return 0;
}
H maze
//这道题是一道简单搜索的题目, 搜索其实就算递归处理, 迷宫求解: 题意是n阶方阵中判断能否从左上角走到右下角, 走法是上下左右.
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 35;
int maze[maxn][maxn], vis[maxn][maxn]; //vis表示是否走过
int T, n;
int action[4][2] = {{1,0}, {0,1}, {-1,0}, {0,-1}};
int flag;
void Dfs(int x, int y)
{ //迷宫走到x,y时
if(x==n && y == n){
flag = 1;
return; //1表示可走
}
for(int i = 0; i < 4; i++){
int tx = x+action[i][0], ty = y+action[i][1];
if(!vis[tx][ty] && maze[tx][ty] && tx>=1 && tx<=n && ty>=1 && ty<=n){
vis[tx][ty] = 1;
Dfs(tx, ty);
vis[tx][ty] = 0; //回溯法处理
}
}
return; //0表示不可走
}
int main()
{
scanf("%d",&T);
while(T--){
memset(maze, 0, sizeof(maze)); //初始化
memset(vis, 0, sizeof(vis));
flag = 0;
scanf("%d",&n);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
scanf("%d",&maze[i][j]);
vis[1][1] = 1;
Dfs(1, 1); //初始状态
if(flag)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
I 开心报道
//最简单的动态规划问题 - 01背包问题, 定义dp[i][j]作为一个状态, 然后根据题意寻得状态转移方程dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i]);
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <cmath>
#include <map>
using namespace std;
#define ms(x, n) memset(x,n,sizeof(x));
typedef long long LL;
const LL maxn = 1e5+10;
int W, n, w[maxn], v[maxn];
int dp[110][maxn]; //在前i个物品中选容量不超过j时的最大价值
int main()
{
cin >> n >> W;
for(int i = 1; i <= n; i++)
cin >> w[i] >> v[i];
//动态规划
ms(dp, 0);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= W; j++){
if(j >= w[i])
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i]);
else
dp[i][j] = dp[i-1][j];
}
cout << dp[n][W] << endl;
return 0;
}
J 阶乘的和
//高精度模板即可
#include <algorithm> // max
#include <cassert> // assert
#include <cstdio> // printf,sprintf
#include <cstring> // strlen
#include <iostream> // cin,cout
#include <string> // string类
#include <vector> // vector类
using namespace std;
struct BigInteger {
typedef unsigned long long LL;
static const int BASE = 100000000;
static const int WIDTH = 8;
vector<int> s;
BigInteger &clean() {
while (!s.back() && s.size() > 1)s.pop_back();
return *this;
}
BigInteger(LL num = 0) { *this = num; }
BigInteger(string s) { *this = s; }
BigInteger &operator=(long long num) {
s.clear();
do {
s.push_back(num % BASE);
num /= BASE;
} while (num > 0);
return *this;
}
BigInteger &operator=(const string &str) {
s.clear();
int x, len = (str.length() - 1) / WIDTH + 1;
for (int i = 0; i < len; i++) {
int end = str.length() - i * WIDTH;
int start = max(0, end - WIDTH);
sscanf(str.substr(start, end - start).c_str(), "%d", &x);
s.push_back(x);
}
return (*this).clean();
}
BigInteger operator+(const BigInteger &b) const {
BigInteger c;
c.s.clear();
for (int i = 0, g = 0;; i++) {
if (g == 0 && i >= s.size() && i >= b.s.size()) break;
int x = g;
if (i < s.size()) x += s[i];
if (i < b.s.size()) x += b.s[i];
c.s.push_back(x % BASE);
g = x / BASE;
}
return c;
}
BigInteger operator-(const BigInteger &b) const {
assert(b <= *this); // 减数不能大于被减数
BigInteger c;
c.s.clear();
for (int i = 0, g = 0;; i++) {
if (g == 0 && i >= s.size() && i >= b.s.size()) break;
int x = s[i] + g;
if (i < b.s.size()) x -= b.s[i];
if (x < 0) {
g = -1;
x += BASE;
}
else g = 0;
c.s.push_back(x);
}
return c.clean();
}
BigInteger operator*(const BigInteger &b) const {
int i, j;
LL g;
vector<LL> v(s.size() + b.s.size(), 0);
BigInteger c;
c.s.clear();
for (i = 0; i < s.size(); i++) for (j = 0; j < b.s.size(); j++) v[i + j] += LL(s[i]) * b.s[j];
for (i = 0, g = 0;; i++) {
if (g == 0 && i >= v.size()) break;
LL x = v[i] + g;
c.s.push_back(x % BASE);
g = x / BASE;
}
return c.clean();
}
BigInteger operator/(const BigInteger &b) const {
assert(b > 0); // 除数必须大于0
BigInteger c = *this; // 商:主要是让c.s和(*this).s的vector一样大
BigInteger m; // 余数:初始化为0
for (int i = s.size() - 1; i >= 0; i--) {
m = m * BASE + s[i];
c.s[i] = bsearch(b, m);
m -= b * c.s[i];
}
return c.clean();
}
BigInteger operator%(const BigInteger &b) const { //方法与除法相同
BigInteger c = *this;
BigInteger m;
for (int i = s.size() - 1; i >= 0; i--) {
m = m * BASE + s[i];
c.s[i] = bsearch(b, m);
m -= b * c.s[i];
}
return m;
}
// 二分法找出满足bx<=m的最大的x
int bsearch(const BigInteger &b, const BigInteger &m) const {
int L = 0, R = BASE - 1, x;
while (1) {
x = (L + R) >> 1;
if (b * x <= m) { if (b * (x + 1) > m) return x; else L = x; }
else R = x;
}
}
BigInteger &operator+=(const BigInteger &b) {
*this = *this + b;
return *this;
}
BigInteger &operator-=(const BigInteger &b) {
*this = *this - b;
return *this;
}
BigInteger &operator*=(const BigInteger &b) {
*this = *this * b;
return *this;
}
BigInteger &operator/=(const BigInteger &b) {
*this = *this / b;
return *this;
}
BigInteger &operator%=(const BigInteger &b) {
*this = *this % b;
return *this;
}
bool operator<(const BigInteger &b) const {
if (s.size() != b.s.size()) return s.size() < b.s.size();
for (int i = s.size() - 1; i >= 0; i--)
if (s[i] != b.s[i]) return s[i] < b.s[i];
return false;
}
bool operator>(const BigInteger &b) const { return b < *this; }
bool operator<=(const BigInteger &b) const { return !(b < *this); }
bool operator>=(const BigInteger &b) const { return !(*this < b); }
bool operator!=(const BigInteger &b) const { return b < *this || *this < b; }
bool operator==(const BigInteger &b) const { return !(b < *this) && !(b > *this); }
};
ostream &operator<<(ostream &out, const BigInteger &x) {
out << x.s.back();
for (int i = x.s.size() - 2; i >= 0; i--) {
char buf[20];
sprintf(buf, "%08d", x.s[i]);
for (int j = 0; j < strlen(buf); j++) out << buf[j];
}
return out;
}
istream &operator>>(istream &in, BigInteger &x) {
string s;
if (!(in >> s)) return in;
x = s;
return in;
}
BigInteger solve(int n)
{
BigInteger ret = 1;
for(int i = n; i > 1; i--)
ret *= i;
return ret;
}
int main()
{
int n;
cin >> n;
BigInteger s = 1;
for(int i = 2; i <= n; i++)
s += solve(i);
cout << s << endl;
}