已经没了的 P8459
bs 鸽鸽的小清新题,我来发篇摸鱼验题人题解。
首先考虑极低分做法,分别是 模拟列竖式 和 FFT,复杂度分别是 \(O(n^2)\) 和 \(O(n\log n)\),都过不了。
其次考虑一些奇怪的语言,比如知名的自带高精的 Python 以及 Ruby(后者似乎慢些),但是他们实现的方法毕竟不是 \(O(n)\) 的,根据亲测,Ruby 和 Python 均能得到 15pts 的高分,但是都寄在了最后一点。
接下来考虑正解,根据上述的努力和高达 \(10^7\) 级的数据我们知道只能搞 \(O(n)\) 的做法,然后关键点在于找到一种 \(O(n)\) 的高精度运算之后我们处理运算完之后的小数据,得出判断。
取舍了一通之后发现高精模低精好像十分靠谱,因为有式子:\(a\equiv a_1\pmod {p},b\equiv b_1\pmod {p}\Rightarrow a\times b\equiv a_1\times b_1\pmod {p}\),但是它并不保证反着也是正确的。
那么怎么证明它的可靠性呢?我们考虑如果毒瘤出题人要卡一个模数的话他就要用 CRT 构造,可以知道如果在 \(10^{18}\) 的范围内取模数的话它只有极小的概率会被卡。
那么实现就很简单了,高精模低精,然后随机一个或多个模数进行计算,多模数的话如果结果均正确就 OK 了。
bs 鸽鸽写的是单模数且不随机的做法,理论上是可以卡的,实际上毒瘤出题人卡掉了 \(998244353,19****17\) 等 \(16\) 个常用模数,实际上如果发现模数被卡就再换一个呗,比如 \(5307\) 就没有被卡(
当然,模数越多常数越大,你写 \(6\) 模数应该是能稳定地跑过去,\(7\) 模数由于常数和评测机状态的问题可能就会被卡了,当然,谁没事干写那么多模数的啊 除了我为了看看 bs 的数据多毒瘤(
由于模数太多影响可读性,这里放一个三模数的代码:
#include<bits/stdc++.h>
using namespace std;
// #define int long long
int mod1,mod2,mod3;
int t;
struct Node{
int x,y,z;
};
inline Node read(){
int s1=0,s2=0,s3=0;char ch=getchar();
while(!isdigit(ch)){ch=getchar();}
while(isdigit(ch)){
s1=s1*10+(ch^48);
s2=s2*10+(ch^48);
s3=s3*10+(ch^48);
if(s1>mod1)s1%=mod1;
if(s2>mod2)s2%=mod2;
if(s3>mod3)s3%=mod3;
ch=getchar();
}
return (Node){s1,s2,s3};
}
signed main(){
cin>>t;
srand(time(0));
while(t--){
mod1=rand()%(int)1e4,mod2=rand()%(int)1e4,mod3=rand()%(int)1e4;
Node a=read(),b=read(),c=read();
if(a.x*b.x%mod1==c.x&&a.y*b.y%mod2==c.y&&a.z*b.z%mod3==c.z)puts("YES");
else puts("NO");
}
return 0;
}
最后说下怎么卡模数,比如 bs 鸽鸽曾经的题解用的模数是 \(123\),那么我们随便写两个数,比如 \(533\times622=331526\),模 \(123\) 是 \(41\),那么构造
1
533 622 41
就能卡掉力!
比如我们同时卡 \(123\) 和 \(12\),那么 $331526\equiv 2\pmod{12} $,然后构造 \(41+123\times3=410\),它模 \(12\) 是 \(2\),模 \(123\) 是 \(41\),所以就可以卡掉双模数了,多模数同理。
当然,不要叉 bs 的,bs 可爱。
本文来自博客园,作者:{Chthologist7507},转载请注明原文链接:https://www.cnblogs.com/Chthologist7507/articles/16777267.html

浙公网安备 33010602011771号