“浪潮杯”题解(菜鸡选几道简单的)

一、

Return of the Nim

Time Limit: 1000 ms  Memory Limit: 65536 KiB
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:
    1. Choose one pile and remove k(k >0) stones from it;
    2. Remove k stones from all piles, where 1≤kthe 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≤in−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博弈和威佐夫博弈的合体。

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

Time Limit: 2000 ms  Memory Limit: 131072 KiB
Problem Description

With given integers a,b,c, you are asked to judge whether the following statement is true: "For any x, if a+bx+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

Time Limit: 2000 ms  Memory Limit: 524288 KiB
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

Time Limit: 1000 ms Memory Limit: 65536 KiB
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;
}
*/


还有好多题没空一道一道过了,等基础算法学全了再说吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值