算法:中国剩余定理(板子)+快速乘
原题链接:
戳一戳-》猜数字
原题:
题目描述
现有两组数字,每组k个,第一组中的数字分别为:a1,a2,…,ak表示,第二组中的数字分别用b1,b2,…,bk表示。其中第二组中的数字是两两互素的。求最小的非负整数n,满足对于任意的i,n - ai能被bi整除。
输入格式
输入数据的第一行是一个整数k,(1 ≤ k ≤ 10)。接下来有两行,第一行是:a1,a2,…,ak,第二行是b1,b2,…,bk
输出格式
输出所求的整数n。
输入输出样例
输入
3
1 2 3
2 3 5
输出
23
说明/提示
所有数据中,第一组数字的绝对值不超过109(可能为负数),第二组数字均为不超过6000的正整数,且第二组里所有数的乘积不超过1018
每个测试点时限1秒
注意:对于C/C++语言,对64位整型数应声明为long long,如使用scanf, printf函数(以及fscanf, fprintf等),应采用%lld标识符。
题意:
就是求一个数 X ,使它满足 对于任意的ai,bi,使X%bi=ai。然后给你多组 ai , bi ,求解X。
思路:
很明显这是一道中国剩余定理的板子题,而且题中提到第二组数据两两之间互为素数,也同时表明这是一道标准的中国剩余定理而不是拓展中国剩余定理。所以套班子就完了。然后我就愉快地WA了最后一组数据。然后看了一下题解才知道最后一组数据会爆long long,然后我又拿来了快速乘板子,然后又愉快地TLE,TLE,TLE。Orz.最后有发现了神奇的预处理数据(将数据先取模,防止数太大导致快速乘,变慢(甚至还不如直接乘))。具体那两行代码下面有标注。
AC代码:
代码注释(为了你们能看懂QAQ,给个赞吧):
moshu[]指的是用来取模的数;
yvshu[]指的是取模后的余数;
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1;
ll read()///快读(见博主 分类(黑科技) 一栏)
{
ll f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return x*f;
}
ll qui_mul(ll a,ll b,ll mod)
{
ll ans=0;
while(b)
{
ans=(ans+(b%2*a)%mod)%mod;
a=(a<<1)%mod;
b>>=1;
}
return ans;
}
ll ex_gcd(ll a,ll b,ll &x,ll &y)
{
if(a==0&&b==0)
return 0;
if(b==0){x=1;y=0;return a;}
ll g=ex_gcd(b,a%b,x,y),tmp=x;
x=y;y=tmp-a/b*y;
return g;
}
ll china(ll moshu[],ll yvshu[],int num)///要求除数必须全是质数
{
ll gongbei=1,ans=0,temp,x,y,i;
for(i=0;i<num;i++)
{
gongbei*=moshu[i];
}
for(i=0;i<num;i++)
{
temp=gongbei/moshu[i];///除了moshu[i]之外的公倍数
ex_gcd(temp,moshu[i],x,y);///取逆元(同余模定理)
x=(x%moshu[i]+moshu[i])%moshu[i];///神奇的一行代码,TLE,TLE,哭了哭了
ans=(ans+qui_mul(qui_mul(temp,x,gongbei),yvshu[i],gongbei))%gongbei;///因为要求出最小的合适解;
}
return (ans+gongbei)%gongbei;
}
int main()
{
int n;
scanf("%d",&n);
ll moshu[n],yvshu[n];
for(int i=0;i<n;i++)
{
yvshu[i]=read();
}
for(int i=0;i<n;i++)
{
moshu[i]=read();
}
for(int i=0;i<n;i++)
yvshu[i]=(yvshu[i]%moshu[i]+moshu[i])%moshu[i];///(先对数据进行预处理,减少数据的大小,由于题目中可能是负数所以还要转化成正数(好像与补码反码有关),否则就会TLE,上面原因相同)神奇的一行代码,哭了哭了,
ll ans=china( moshu,yvshu,n);
printf("%lld\n",ans);
}
总结:
这一道题虽然是一道板子题,但是我自己还是没能独立写出来,Why?
菜!!!
很多板子的适用条件都没有搞清楚,所以胡乱使用导致BUG不断。
好好学吧~~
告诫:
学就完了!!!