【题解】[SCOI2011] 飞镖

模拟题

红靶子的我们先不考虑。

如果是 {1,2,2} , {2,2,3} 这种只涉及两种倍数的话,我们想到不定方程:

ax+by =c 的通解形式(a,b,c 为常数),从而探讨 x,y 在规定取值内是否有解。

探讨 {1,2,3} 的情况。

这个时候不难发现 x ∈ [ 1 , 6 k ] x\in [1,6k] x[1,6k] 是有解的。

如果你暴力每种情况枚举的话会比较麻烦。

我们可以递归求解:(当然这是个笨方法)

对于轮数为 1 的情况相对较少,直接求解。

对于轮数等于 2 的情况,有几种情形:

第一种,有一个为 M 的靶

第二种,有一个为 2M 的靶

第三种,没有红心靶

组合形式为

{2,2}, {1,2} , {2,3}

如果之前有过 2M 的靶,还可以是:

{3,3} , {1,3}

对于轮数等于 3 的情况,有几种情形:

第一种,有一个为 M 的靶

第二种,有一个为 2M 的靶

第三种,没有红心靶

组合形式为

{1,2,3} , {2,2,3} , {2,3,3}

讲一下这个不定方程到底怎么求。

请添加图片描述

#include <bits/stdc++.h>
#define ll long long
using namespace std;
//贪心
int T, res;
ll A1, B1, C1, D1, K1;
ll A2, B2, C2, D2, M1;
ll A3, B3, C3, D3, X1;
bool check(ll X, ll Y, ll M) {
    ll l = -M - 3 * floor((X - M) / 2.0), r = -M - 3 * ceil((1 - M) / 2.0);

    if (r >= 1 && l <= Y) {
        return 1;
    }

    return 0;
}
bool solve(int k, ll K, ll M, ll X, int limit) {
    if (X == 0) {
        return (limit == 1);
    }

    if (k == 1) {
        if (X == 2 * M || (X % 2 == 0 && X / 2 <= K)) {
            return 1;
        }

        if (limit) {
            if (X <= K || (X % 3 == 0 && X / 3 <= K) || X == M) {
                return 1;
            }
        }

        return 0;
    }

    if (X >= M && solve(k - 1, K, M, X - M, limit))
        return 1;

    if (X >= 2 * M && solve(k - 1, K, M, X - 2 * M, 1))
        return 1;

    if (solve(k - 1, K, M, X, limit))
        return 1;

    if (k == 2) {
        if (X % 2 == 0 && X / 2 <= 2 * K)
            return 1;

        if (X > 1 && X <= 3 * K)
            return 1;

        if (check(K, K, X))
            return 1;

        if (limit) {
            if (X % 3 == 0 && X / 3 <= 2 * K)
                return 1;

            if (X <= 4 * K)
                return 1;
        }

        return 0;
    }

    if (k == 3) {
        if (X <= 6 * K)
            return 1;

        if (check(2 * K, K, X) || check(K, 2 * K, X))
            return 1;

        return 0;
    }

    return 0;
}
int main() {
    //  freopen("data.in","r",stdin);
    //  freopen("dart.in","r",stdin);
    //  freopen("dart.out","w",stdout);
    scanf("%d", &T);
    scanf("%lld%lld%lld%lld%lld", &A1, &B1, &C1, &D1, &K1);
    scanf("%lld%lld%lld%lld%lld", &A2, &B2, &C2, &D2, &M1);
    scanf("%lld%lld%lld%lld%lld", &A3, &B3, &C3, &D3, &X1);
    //  solve(3,20,32,205,0);
    res += solve(3, K1, M1, X1, 0);

    for (int i = 2; i <= T; i++) {
        K1 = (((__int128)A1 * K1 * K1 + B1 * K1 % D1 + C1) % D1) + 20;
        M1 = (((__int128)A2 * M1 * M1 + B2 * M1 % D2 + C2) % D2) + 20;
        X1 = (((__int128)A3 * X1 * X1 + B3 * X1 % D3 + C3) % D3) + 20;
        res += solve(3, K1, M1, X1, 0);
        //      if(solve(3,K1,M1,X1,0)) {
        //          printf("%lld %lld %lld\n",K1,M1,X1);
        //      }
    }

    printf("%d", res);
}
// 20 32 205
//1
//0 0 0 0 100
//0 0 0 0 1000
//0 0 0 0 1001
posted @ 2022-04-02 14:06  仰望星空的蚂蚁  阅读(17)  评论(0)    收藏  举报  来源