P3277 [SCOI2011] 飞镖
大分讨。
首先有结论 \(5k\) 一下的分数除了 \(5k-1\) 都可以用两次凑出来(不打红心)
以下用 \(num\) 代表数字,\(heart\) 代表红心。
- \(num\ num\ num\)
- 前两个至少有一个不是 \(3\) 倍。
把前两个合起来,最有一个只能是偶数,单独算。 - 前两个都是 \(3\) 倍。
把一个 \(3\) 倍和一个 \(2\) 倍合起来,剩下一个 \(3\) 倍单独算。
- 前两个至少有一个不是 \(3\) 倍。
- \(num\ heart\ num\)
把两个数字合起来,红心 \(3\) 种情况(不选,\(1\) 倍,\(2\) 倍)枚举一下。 - \(heart\ heart\ num\)
两个红心 \(0\) 到 \(4\) 被枚举一下,最后一个单独算。 - \(num\ num\ heart\)
两个数字合起来算,最后一个红心只能是 \(2\) 倍 - \(num\ heart\ heart\)
两个红心 \(2\) 到 \(4\) 倍,剩一个数字单独算。 - \(heart\ heart\ heart\)
三个红心,\(2\) 到 \(6\) 倍,直接判断
一些细节:要注意判断负数,要开 \(long\ long\),最后一个不能是 \(0\)
时间复杂度 \(\mathcal O(T)\)。
代码
/*
Luogu P3277 [SCOI2011] 飞镖
2026-03-12
*/
#include<bits/stdc++.h>
using namespace std;
namespace IO{
template<typename T>
inline void read(T&x){
x=0;char c=getchar();bool f=0;
while(!isdigit(c)) c=='-'?f=1:0,c=getchar();
while(isdigit(c)) x=x*10+c-'0',c=getchar();
f?x=-x:0;
}
template<typename T>
inline void write(T x){
if(x==0){putchar('0');return ;}
x<0?x=-x,putchar('-'):0;short st[50],top=0;
while(x) st[++top]=x%10,x/=10;
while(top) putchar(st[top--]+'0');
}
inline void read(char&c){c=getchar();while(isspace(c)) c=getchar();}
inline void write(char c){putchar(c);}
inline void read(string&s){s.clear();char c;read(c);while(!isspace(c)&&~c) s+=c,c=getchar();}
inline void write(string s){for(int i=0,len=s.size();i<len;i++) putchar(s[i]);}
template<typename T>inline void write(T*x){while(*x) putchar(*(x++));}
template<typename T,typename...T2> inline void read(T&x,T2&...y){read(x),read(y...);}
template<typename T,typename...T2> inline void write(const T x,const T2...y){write(x),putchar(' '),write(y...),sizeof...(y)==1?putchar('\n'):0;}
}using namespace IO;
#define int long long
int a1,b1,c1,d1,k,a2,b2,c2,d2,m,a3,b3,c3,d3,x,ans;
bool check1(int z){
int sy=z-5*k;
if(sy<=2*k&&sy>=2&&sy%2==0) return 1;
if((sy+2)<=2*k) return 1;
if(sy<=3*k&&sy>=0&&sy%3==0) return 1;
if((sy+2)<=3*k) return 1;
return 0;
}
bool check2(int z){
if(z<2) return 0;
if(z==5*k-1||z>5*k) return 0;
return 1;
}
bool check3(int z){
if(z<=0||z>2*k) return 0;
return z%2==0;
}
bool check4(int z){
if(z<0) return 0;
if(z!=5*k-1&&z<=5*k) return 1;
if(z<=6*k&&z%3==0) return 1;
return 0;
}
bool check5(int z){
if(z<0) return 0;
if(z<=k) return 1;
if(z<=2*k&&z%2==0) return 1;
if(z<=3*k&&z%3==0) return 1;
return 0;
}
void solve(){
int add=0;
if(check1(x)) add=1;//num num num
if(check2(x)||check2(x-m)||check2(x-m-m)) add=1;//num heart num
for(int i=0;i<=4;i++) if(check3(x-m*i)) add=1;//heart heart num
if(check4(x-m-m)) add=1;//num num heart
if(check5(x-m-m)||check5(x-m*3)||check5(x-m*4)) add=1;//heart num heart
for(int i=2;i<=6;i++) if(x==i*m) add=1;//heart heart heart
ans+=add;
k=(a1*k%d1*k+b1*k+c1)%d1+20;
m=(a2*m%d2*m+b2*m+c2)%d2+20;
x=(a3*x%d3*x+b3*x+c3)%d3+20;
}
signed main(){
int T;read(T);
read(a1,b1,c1,d1,k,a2,b2,c2,d2,m,a3,b3,c3,d3,x);
while(T--) solve();
write(ans);
return 0;
}

浙公网安备 33010602011771号