套题链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=104400#problem/A
难度类型:AC不难,C要接触过类似的题,B是博弈要会打表,D是还可以的dp但是题面略坑,E是线段树,第一次写线段树啊。
A
题解
类型:模拟,位运算
统计 1 的个数然后判断就行了。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
LL powmod(LL a,LL b, LL MOD) {LL res=1;a%=MOD;for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}
// head
char s[35];
int main()
{
while (scanf("%s", s) == 1 && s[0] != '#') {
int n = strlen(s);
int cnt = 0;
for (int i = 0; i < n; i++) {
if (s[i] == '1') cnt++;
}
s[n-1] = ((s[n-1]=='e') != (cnt&1)) ? '0' : '1';
puts(s);
}
return 0;
}
B
题解
类型:博弈
似乎是叫做巴什博弈,我是记忆化搜索打表做的,很容易看出来是斐波那契数列,然后预处理判断即可。了解必胜态和必败态许多博弈题目不知道对应的模型也可以进行猜测,当然前提是结论不是非常复杂。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
LL powmod(LL a,LL b, LL MOD) {LL res=1;a%=MOD;for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}
// head
int dp[35][35];
bool dfs(int n, int last) {
if (dp[n][last] != -1) return dp[n][last];
if (n == 0) return dp[n][last] = false;
if (n == 1 || n <= last) return dp[n][last] = true;
int lim = last == 0 ? n-1 : min(n, 2*last);
for (int i = 1; i <= lim; i++) {
if (!dfs(n-i, i)) return dp[n][last] = true;
}
return dp[n][last] = false;
}
void bruteForce() {
memset(dp, -1, sizeof dp);
for (int i = 2; i <= 30; i++) {
printf("%d: %d\n", i, dfs(i, 0));
}
}
int fib[50];
int main()
{
//bruteForce();
fib[1] = 1;
for (int i = 2; i < 47; i++) {
fib[i] = fib[i-1]+fib[i-2];
}
int n;
while (scanf("%d", &n) == 1 && n) {
bool ans = false;
for (int i = 2; i < 47; i++) {
if (fib[i] == n) ans = true;
}
puts(ans ? "Second win" : "First win");
}
return 0;
}
C
题解
类型:数学,斐波那契
题目不难,不过需要接触过类似题。
首先需要知道一个结论就是limi→∞(fibi/fibi−1)=φ=5√+12 , φ 就是黄金系数。
然后嘞就有以下的结论:
bitanslog10ans=log10(fibst×φn−st)=log10(fibst)+(n−st)log10φ=bit−⌊bit−3⌋=10anslog10为了降低误差,需要在对数下运算出指数。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
LL powmod(LL a,LL b, LL MOD) {LL res=1;a%=MOD;for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}
// head
double phi = (1+sqrt(5))/2;
const int N = 21;
int fib[N];
int solve(int n) {
double bit = log10(fib[N-1])+(n-N+1)*log10(phi);
return pow(10, bit-floor(bit)+3);
}
int main()
{
fib[0] = 0;
fib[1] = 1;
for (int i = 2; i < N; i++) {
fib[i] = fib[i-1]+fib[i-2];
}
int n;
while (scanf("%d", &n) == 1) {
if (n < N) printf("%d\n", fib[n]);
else printf("%d\n", solve(n));
}
return 0;
}
D
题解
类型:dp
对轮数还有进行到技能的天数进行dp,环形进行转移,边边角角比较蛋疼,需要注意题面中战斗力 6 不可战胜。需要注意要记录状态是否可达,因为如果说从中间开始就能转移,那么可以早结束进行下次技能,会WA。
另开的题解:http://blog.youkuaiyun.com/xc19952007/article/details/50589188
E
题解
类型:线段树,数论
比较裸的线段树,学了就会了,单点更新+区间更新+延迟。然后线性筛处理下素数。
另开的题解:http://blog.youkuaiyun.com/xc19952007/article/details/50589156