虽然AT评的是问号题,但并不是特别难。设
题目要求的就是 \(f(g_1-1,r_1+g_1,g_2-1,g_2+r_2,g_3-1,g_3+r_3)\) 。
考虑如何求解 \(f\),有一个思路就是枚举 \(x\) 对 \(y_1\),\(y_2\),\(y_3\) 分别取模的值 \(b_1\),\(b_2\),\(b_3\)。找到一个合法的 \(x\) 的充要条件即 \(b_1\equiv b_2\bmod \gcd(y_1,y_2)\),对于任意两组都要满足该条件。
这启发我们对于 \(\bmod y_2\) 和 \(\bmod y_3\) 相同的 \(b_1\) 对于 \(b_2\),\(b_3\) 合法的限制是相同的。
于是我们求出 \(v=lcm(\gcd(y_1,y_2),\gcd(y_1,y_3))\),当 \(v\ne y_1\) 时,\((x\bmod y_1)\bmod v\) 相同时的答案是一样的。我们便可将问题简化为子问题,前面有 \(\lfloor \frac{x_1}{v}\rfloor\) 个完整的组,答案都是 \(f(v-1,v,x_2,y_2,x_3,y_3)\),余项单独处理为 \(f(x_1\bmod v,v,x_2,y_2,x_3,y_3)\)。若 \(v=y_1\) 则依次对 \(y_2\),\(y_3\) 做类似操作,容易发现递归层数最多为 3,也就是对 \(y_1\),\(y_2\),\(y_3\) 各做一次操作进行递归。
若对于 \(y_1\),\(y_2\),\(y_3\) 均无法进行上述操作,那么说明它们满足任意两数的最小公倍数时另一个数的倍数。则此时一定存在正整数 \(x,y,z,j\),满足 \(x,y,z\) 两两互质使得 \(y_1=xjy\),\(y_2=xzj\),\(y_3=yzj\)。我们令 \(x> y> z\),则 \(y,z\) 均小于 \(\sqrt{2e12}\)。
那么我们可以枚举对于 \(y_1\),\(y_2\) 合法的数,具体的可以将两个初始为 \([0,x_1]\),\([0,x_2]\) 的区间向后移动,每次取区间交集判断区间内对于 \(y_3\) 合法的数的个数,再将较小的区间移动,直到两个区间的左端点都为 \(\gcd(y_1,y_2,y_3)\)。最终答案为前面统计的个数乘 \(\frac{y_1y_2y_3}{\gcd(y_1,y_2,y_3)}\)。
最终复杂度为 \(O(\sqrt{g+r})\)。
code:
#include <bits/stdc++.h>
#define ll long long
#define LL __int128
using namespace std;
const ll N=1e6+5,mod=119*(1ll<<23)+1;
inline LL rd()
{char c;int f=1;while(!isdigit(c=getchar())) if(c=='-') f=-1;LL x=(c^48);while(isdigit(c=getchar())) x=(x*10)+(c^48);return x*f;
}
LL g1,g2,g3,r1,r2,r3,S;
LL gcd(LL x,LL y){return y?gcd(y,x%y):x;}
LL lcm(LL x,LL y){return x/gcd(x,y)*y;}
ll get(ll x,ll g,ll r){return x/r*(g+1)+min(x%r,g);}
ll sol(ll g1,ll r1,ll g2,ll r2,ll g3,ll r3)
{ll s=lcm(gcd(r1,r2),gcd(r1,r3));if(s!=r1) return (1ll*(g1/s)%mod*sol(s-1,s,g2,r2,g3,r3)+sol(g1%s,s,g2,r2,g3,r3))%mod;s=lcm(gcd(r1,r2),gcd(r2,r3));if(s!=r2) return (1ll*(g2/s)%mod*sol(s-1,s,g1,r1,g3,r3)+sol(g2%s,s,g1,r1,g3,r3))%mod;s=lcm(gcd(r2,r3),gcd(r1,r3));if(s!=r3) return (1ll*(g3/s)%mod*sol(s-1,s,g1,r1,g2,r2)+sol(g3%s,s,g1,r1,g2,r2))%mod;if(r1<r2) swap(r1,r2),swap(g1,g2);if(r2<r3) swap(r3,r2),swap(g3,g2);if(r1<r3) swap(r1,r3),swap(g1,g3);ll s1=0,e1=g1,s2=0,e2=g2,res=0;while(1){if(s1==s2&&s1%r3==0&&s1!=0) break;ll l=max(s1,s2),r=min(e1,e2);if(l<=r) res+=get(r,g3,r3)-get(l-1,g3,r3);if(e1<e2) s1+=r1,e1+=r1;else s2+=r2,e2+=r2;}return ((LL)r1*r2/s1*r3)%mod*(res%mod)%mod;
}
int main()
{g1=rd(),r1=rd(),g2=rd(),r2=rd(),g3=rd(),r3=rd();r1+=g1,r2+=g2,r3+=g3;g1--,g2--,g3--;S=r1*r2*r3;cout<<sol(g1,r1,g2,r2,g3,r3);return 0;
}