一、
Return of the Nim
Problem Description
Sherlock and Watson are playing the following modified version of Nim game:
- There are n piles of stones denoted as ,,...,, and n is a prime number;
- Sherlock always plays first, and Watson and he move in alternating turns. During each turn, the current player must perform either of the following two kinds of moves:
- Choose one pile and remove k(k >0) stones from it;
- Remove k stones from all piles, where 1≤k≤the size of the smallest pile. This move becomes unavailable if any pile is empty.
- Each player moves optimally, meaning they will not make a move that causes them to lose if there are still any better or winning moves.
Giving the initial situation of each game, you are required to figure out who will be the winner
Input
The first contains an integer, g, denoting the number of games. The 2×g subsequent lines describe each game over two lines:
1. The first line contains a prime integer, n, denoting the number of piles.
2. The second line contains n space-separated integers describing the respective values of ,,...,.
- 1≤g≤15
- 2≤n≤30, where n is a prime.
- 1≤pilesi≤ where 0≤i≤n−1
Output
For each game, print the name of the winner on a new line (i.e., either "Sherlock
" or "Watson
")
Sample Input
2 3 2 3 2 2 2 1
Sample Output
Sherlock Watson
Nim博弈:
如果石子堆们异或为0, 则先手必输。
威佐夫博弈:
对于两堆石子n1<n2,如果floor((n2-n1)*(1+sqrt(5.0))/2.0) == n2,先手必胜。
#include <bits/stdc++.h>
using namespace std;
#define N 100001
int main()
{
int n, a[N], b, c;
int t;
scanf("%d", &t);
while(t--){
scanf("%d", &n);
if(n == 2){
scanf("%d%d", &b, &c);
if(b > c)
swap(b, c);
if(int((c - b) * (1 + sqrt(5.0)) / 2.0) == b)
printf("Watson\n");
else
printf("Sherlock\n");
}
else{
for(int i = 0; i < n; i++)
scanf("%d", &a[i]);
int ans = a[0];
for(int i = 1; i < n; i++)
ans ^= a[i];
printf(!ans?"Watson\n":"Sherlock\n");
}
}
return 0;
}
quadratic equation
Problem Description
With given integers a,b,c, you are asked to judge whether the following statement is true: "For any x, if a⋅+b⋅x+c=0, then x is an integer."
Input
The first line contains only one integer T(1≤T≤2000), which indicates the number of test cases.
For each test case, there is only one line containing three integers a,b,c(−5≤a,b,c≤5).
Output
or each test case, output “YES
” if the statement is true, or “NO
” if not.
Sample Input
3 1 4 4 0 0 1 1 3 1
Sample Output
YES YES NO
这题真尼玛坑爹,WA了一万遍,竟然卡精度了。
另外无数解的情况算假,无解的情况算真。
#include <bits/stdc++.h>
using namespace std;
int main()
{
freopen("date.txt", "r", stdin);
int a, b, c, t;
scanf("%d", &t);
while(t--){
scanf("%d%d%d", &a, &b, &c);
double qr = b * b - 4 * a * c;
if(b * b - 4 * a * c < 0){
printf("YES\n");
continue;
}
if(a == 0){
if(b != 0 && c != 0){
if(c % b == 0){
printf("YES\n");
}
else{
printf("NO\n");
}
}else if(b == 0 && c == 0){
printf("NO\n");
}else{
printf("YES\n");
}
continue;
}
int q = sqrt(qr);
if(fabs(sqrt(qr) - q) < 1e-8 && (-b + q) % (2 * a) == 0 && (-b - q) % (2 * a) == 0)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
Parity check
Problem Description
Fascinated with the computer games, Gabriel even forgets to study. Now she needs to finish her homework, and there is an easy problem:
f(n)=
She is required to calculate f(n) mod 2 for each given n. Can you help her?
Input
Multiple test cases. Each test case is an integer n(0≤n≤) in a single line.
Output
For each test case, output the answer of f(n)mod2.
Sample Input
2
Sample Output
1
会发现奇偶性是会传递的,有规律的出现。
最后判断结果是否为3的倍数就好了,代码就不上了,是把每一位的数字加起来求和是否是三的倍数来判断的。
fireworks
Problem Description
Hmz likes to play fireworks, especially when they are put regularly.
Now he puts some fireworks in a line. This time he put a trigger on each firework. With that trigger, each firework will explode and split into two parts per second, which means if a firework is currently in position x, then in next second one part will be in position x−1 and one in x+1. They can continue spliting without limits, as Hmz likes.
Now there are n fireworks on the number axis. Hmz wants to know after T seconds, how many fireworks are there in position w?
Input
Input contains multiple test cases.
For each test case:
- The first line contains 3 integers n,T,w(n,T,|w|≤10^5)
- In next n lines, each line contains two integers xi and ci, indicating there are ci fireworks in position xi at the beginning(ci,|xi|≤10^5).
Output
For each test case, you should output the answer MOD 1000000007.
Sample Input
1 2 0 2 2 2 2 2 0 3 1 2
Sample Output
2 3
我能想到杨辉三角加逆元求组合数,但是以前没敲过这种题目,想到了算法也凉凉。
看了大佬的代码后努力分析,写了些注释,还是觉得没全懂。
首先是求逆元,大佬博客是费马小定理求的,我自己用逆元写了个。
然后是组合数的递推推导,一层for O(nlogn)搞定组合数。
最后是特大佬的分奇偶、、不会啊,想不到啊,凉啊。。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define N 100005
ll C[N];
ll mod = 1000000007;
ll n, t, w, c, x, ans, dis, mid, idx;
/**
ll power(ll a, ll b)
{
ll tmp = 1;
while(b){
if(b & 1)
tmp = (tmp * a) % mod;
a = (a * a) % mod;
b >>= 1;
}
return tmp;
}
///费马小定理
void getc(ll t)
{
C[0] = 1;
for(int i = 1; i <= t; i++){
C[i] = (C[i - 1] * (t - i + 1) % mod * power(i, mod - 2) )% mod;
// cout << i << ' ' << C[i] << endl;
}
}
*/
void exgcd(ll a, ll b, ll & x, ll & y)
{
if(b){
exgcd(b, a % b, y, x);
y -= (a / b) * x;
}
else{
x = 1;
y = 0;
}
}
ll rev(ll a, ll m)
{
ll x, y;
exgcd(a, m, x, y);
return (x % m + m) % m;
}
void getc(ll t)
{
C[0] = 1;
for(int i = 1; i <= t; i++){
C[i] = C[i - 1] * (t - i + 1) % mod * rev(i, mod) % mod;
}
}
int main()
{
//freopen("date.txt", "r", stdin);
while(scanf("%lld%lld%lld", &n, &t, &w) != EOF){
ans = 0;
mid = (t + 1) / 2;///最底层的长度的一半
getc(t);///求逆元
for(int i = 0; i < n; i++){
scanf("%lld%lld", &x, &c);
///是所求点到原始点的距离
dis = abs(x - w);
///如果距离大于底层的长度那么怎么都炸不到。
///如果距离和t的奇偶性不同,那么刚好嵌在0里面
if(dis > t || (dis & 1) != (t & 1)) continue;
///按道理说组合数的性质从向左向右偏移都行,但是不分奇偶会WA
///我觉得好像是因为奇偶会影响mid是偏左边还是偏右边
idx = mid + ( (t & 1) ? dis / 2 : -1 * dis / 2 );
ans += c * C[idx];
ans %= mod;
}
printf("%lld\n", ans);
}
return 0;
}
/**
#include <cstdio>
#include <algorithm>
#include <iostream>
#include<vector>
#include<cmath>
#include<set>
#include<cstring>
#include<sstream>
#include<queue>
#include<map>
using namespace std;
typedef long long ll;
const int maxn = 1299709 + 10;
const int maxt = 100200;
const int inf = 0x3f3f3f3f;
const ll INF = 0x7f7f7f7f7f7f7f7f;
const int mod = 1e9 + 7;
const double pi = acos(-1.0);
const double eps = 1e-8;
int a[maxn];
ll C[maxn];
ll quick_mod(ll x, int n){
ll ret = 1;
while(n){
if(n & 1) ret = ret * x % mod;
x = x * x %mod;
n >>= 1;
}
return ret;
}
void init(int t){
C[0] = 1;
for(int i = 1; i <= t; ++i){
C[i] = C[i - 1] * (t - i + 1) % mod * quick_mod(i, mod - 2) % mod;
// cout << i << " " << C[i] << endl;
}
}
ll solve(ll x, int w, int l){
int d = abs(x - w);
ll sum = 0;
if(l & 1){
if(d < l && d % 2 == 0)
sum += C[l / 2 - d / 2];
}
else{
if(d < l && d & 1)
sum += C[l / 2 + (d - 1) / 2];
}
return sum;
}
int main(){
freopen("date.txt", "r", stdin);
int n, t, w;
while(scanf("%d%d%d", &n, &t, &w) == 3){
ll ans = 0;
init(t);
for(int i = 0; i < n; ++i){
int x, c;
scanf("%d%d", &x, &c);
ans += c * solve(x, w, t + 1);
ans %= mod;
}
printf("%lld\n", ans);
}
return 0;
}
*/
还有好多题没空一道一道过了,等基础算法学全了再说吧。