洛谷传送门
BZOJ传送门
题目描述
飞镖是在欧洲颇为流行的一项运动。它的镖盘上分为 20 20 20个扇形区域,分别标有 1 1 1到 20 20 20的分值,每个区域中有单倍、双倍和三倍的区域,打中对应的区域会得到分值乘以倍数所对应的分数。
例如打中 18 18 18分里面的三倍区域,就会得到 54 54 54分。
另外,在镖盘的中央,还有”小红心“和”大红心“,分别是 25 25 25分和 50 50 50分。
通常的飞镖规则还有一条,那就是在最后一镖的时候,必须以双倍结束战斗,才算获胜。也就是说,当还剩12分的时候,必须打中双倍的 6 6 6才算赢,而打中单倍的 12 12 12或者三倍的 4 4 4则不算。
特别的,”大红心“也算双倍(双倍的 25 25 25)。在这样的规则下, 3 3 3镖能解决的最多分数是 170 170 170分(两个三倍的 20 20 20,最后用大红心结束)。
现在,lxhgww把原来的 1 1 1到 20 20 20分的分值变为了 1 1 1到 K K K分,同时把小红心的分数变为了 M M M分(大红心是其双倍),现在lxhgww想知道能否在 3 3 3镖内(可以不一定用满 3 3 3镖)解决 X X X分。同样的,最后一镖必须是双倍(包括大红心)。
输入输出格式
输入格式:
输入的第一行是一个整数 T T T,包括了 T T T组数据。
第二行是 5 5 5个整数, A 1 , B 1 , C 1 , D 1 , K 1 A_1,B_1,C_1,D_1,K_1 A1,B1,C1,D1,K1,表示第一组数据的镖盘是从 1 1 1到 K 1 K_1 K1分的,随后数据的镖盘由公式 K i = ( A 1 K i − 1 2 + B 1 K i − 1 + C 1 ) m o d D 1 + 20 K_i=(A_1K^2_{i-1}+B_1K_{i-1}+C_1)mod D_1 + 20 Ki=(A1Ki−12+B1Ki−1+C1)modD1+20决定,其中第 i ( 1 < i ≤ T ) i(1<i\le T) i(1<i≤T)组数据的镖盘是从 1 1 1到 K i K_i Ki分的。
第三行是 5 5 5个整数, A 2 , B 2 , C 2 , D 2 , M 1 A_2,B_2,C_2,D_2,M_1 A2,B2,C2,D2,M1,表示第一组数据的小红心 M 1 M_1 M1分的,随后数据的镖盘由公式 M i = ( A 2 M i − 1 2 + B 2 M i − 1 + C 2 ) m o d D 2 + 20 M_i=(A_2M^2_{i-1}+B_2M_{i-1}+C_2)mod D_2 + 20 Mi=(A2Mi−12+B2Mi−1+C2)modD2+20决定,其中第 i ( 1 < i ≤ T ) i(1<i\le T) i(1<i≤T)组数据的小红心是 M i M_i Mi分。
第四行是 5 5 5个整数, A 3 , B 3 , C 3 , D 3 , X 1 A_3,B_3,C_3,D_3,X_1 A3,B3,C3,D3,X1,表示第一组数据需要解决的分数是 X 1 X_1 X1分的,随后数据的镖盘由公式 X i = ( A 3 X i − 1 2 + B 3 X i − 1 + C 3 ) m o d D 3 + 20 X_i=(A_3X^2_{i-1}+B_3X_{i-1}+C_3)mod D_3 + 20 Xi=(A3Xi−12+B3Xi−1+C3)modD3+20决定,其中第 i ( 1 < i ≤ T ) i(1<i\le T) i(1<i≤T)组数据需要解决的分数是 X i X_i Xi分。
输出格式:
一行,包括一个数字,表示这 T T T组数据中,能够被解决的数据数目。
输入输出样例
输入样例#1:
5
1 2 2 10 20
1 3 2 15 25
2 2 5 200 170
输出样例#1:
4
说明
对于30%的数据,保证 1 ≤ T ≤ 20 , 20 ≤ K 1 , M 1 , X 1 , D 1 , D 2 , D 3 ≤ 1000 1\le T\le 20,20\le K_1,M_1,X_1,D_1,D_2,D_3\le 1000 1≤T≤20,20≤K1,M1,X1,D1,D2,D3≤1000
对于100%的数据,保证 1 ≤ T ≤ 1 0 6 , 20 ≤ K 1 , M 1 , X 1 , D 1 , D 2 , D 3 ≤ 1 0 9 1\le T\le 10^6,20\le K_1,M_1,X_1,D_1,D_2,D_3\le 10^9 1≤T≤106,20≤K1,M1,X1,D1,D2,D3≤109
对于所有的数据,保证 0 ≤ A 1 , B 1 , A 2 , B 2 , C 2 , A 3 , B 3 , C 3 ≤ 1 0 9 0\le A_1,B_1,A_2,B_2,C_2,A_3,B_3,C_3 \le 10^9 0≤A1,B1,A2,B2,C2,A3,B3,C3≤109
解题分析
恶心的特判题。
首先有一个结论:在 5 K 5K 5K之内除了 1 1 1和 5 K − 1 5K-1 5K−1都可以用 2 a + 3 b 2a+3b 2a+3b这种形式凑出来, 证明倒着来凑, 发现是每 5 5 5个一个循环就行了。
设 M M M表示小红心, i i i表示其他位置的 1 ∼ 3 1\sim 3 1∼3倍区域。
先考虑没有红心的情况:
i
i,i
i,i,i
前两个比较好判, 最后那个由于 K > 20 K>20 K>20, 如果 X < 2 K X<2K X<2K显然是有解的, X > 2 K X>2K X>2K的情况先搞一个 2 K 2K 2K出来, 剩下的尝试用 2 a + 3 b 2a+3b 2a+3b或 3 a + 3 b 3a+3b 3a+3b的形式凑就好了。
然后是有红心的情况:
-
M,i,i
-
2M,i,i
-
M,M,i
-
2M,M,i
-
2M,2M,i
-
i,i,2M
-
i,M,2M
-
i,2M,2M
-
M,M,2M
-
M,2M,2M
-
2M,2M,2M
-
M,i
-
M,2M
-
i,2M
-
2M
这么直接讨论太麻烦了, 分成几类:
第一类: 4, 5
第二类: 6 , 7, 8, 15
第三类: 9
第四类: 10, 11, 17
第五类: 12, 13, 14, 16, 17
然后大力判就好了…
代码如下:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <algorithm>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define ll long long
ll K, M, X, A[3], B[3], C[3], D[3];
int T, ans;
IN bool c1(R ll val)
{
if (val <= 1 || val == 5 * K - 1) return false;
if (val > 5 * K) return false;
return true;
}
IN bool c2(R ll val)
{
if (val <= 0 || val > 2 * K) return false;
return val % 2 == 0;
}
IN bool c3(R ll val)
{
if (val <= 0 || val > 6 * K) return false;
if (val > 5 * K) return val % 3 == 0;
if (val % 3 == 0) return true;
return val != 1 && val != 5 * K - 1;
}
IN bool c4(R ll val)
{
if (val <= 0 || val > 3 * K) return false;
if (val % 3 == 0) return true;
if (val <= 2 * K && val % 2 == 0) return true;
if (val <= K) return true;
return false;
}
IN bool mul() {return (X == 2 * M) || (X == 3 * M) || (X == 4 * M) || (X == 5 * M) || (X == 6 * M);}
IN bool spj()
{
if (X <= 5 * K && X != 1 && X != 5 * K - 1) return true;
ll del = X - 2 * K;
if (del <= 5 * K && del != 5 * K - 1) return true;
else
{
W (del % 3) del += 2;
if (del > 6 * K) return false;
return true;
}
}
int main(void)
{
scanf("%d", &T);
scanf("%lld%lld%lld%lld%lld", &A[0], &B[0], &C[0], &D[0], &K);
scanf("%lld%lld%lld%lld%lld", &A[1], &B[1], &C[1], &D[1], &M);
scanf("%lld%lld%lld%lld%lld", &A[2], &B[2], &C[2], &D[2], &X);
W (T--)
{
if (spj()) ++ans;
else if (c1(X - M) || c1(X - 2 * M)) ++ans;
else if (c2(X - M) || c2(X - 2 * M) || c2(X - 3 * M) || c2(X - 4 * M)) ++ans;
else if (c3(X - 2 * M)) ++ans;
else if (c4(X - 2 * M) || c4(X - 3 * M) || c4(X - 4 * M)) ++ans;
else if (mul()) ++ans;
K = (A[0] * K % D[0] * K % D[0] + B[0] * K % D[0] + C[0]) % D[0] + 20;
M = (A[1] * M % D[1] * M % D[1] + B[1] * M % D[1] + C[1]) % D[1] + 20;
X = (A[2] * X % D[2] * X % D[2] + B[2] * X % D[2] + C[2]) % D[2] + 20;
}
printf("%d\n", ans);
}