2018年新生中軟ACM程式設計大賽決賽 -題解
阿新 • • 發佈:2019-01-14
今天是院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