题目背景
本题数据已加强,请使用 FFT/NTT,不要再交 Python 代码浪费评测资源。
题目描述
给你两个正整数 a,b,求$ a \times b$.
输入格式
第一行一个正整数,表示 a;
第二行一个正整数,表示 b。
输出格式
输出一行一个整数表示答案。
输入输出样例
输入
114514
1919810
输出
219845122340
说明/提示
【数据范围】
$1\le a,b \le 10^{1000000}$
可能需要一定程度的常数优化。
emmmm,刚开始学FFT/NTT的可能一下子没有反应过来,我们设输入$s$,那么这个数必然能被表示成$s=a_0*10^0+a_1*10^1+a_2*10^2+\cdots $。。。然后就是个愉快的卷积了^_^,只不过要稍微注意一下顺序的问题和边界的处理
以下是AC代码:
/*
实质上就是将一个数变成a_0*10^0+a_1*10+a_2*10^2...然后就可以快乐地卷积了
*/
#include
#include
#include
#include
#include
using namespace std;
#define IOS ios::sync_with_stdio(false);
typedef long long ll;
const int mac=3e6+10;
const int mod=998244353;
ll a[mac],b[mac],rt[5][30];
int r[mac];
string s1,s2;
ll qpow(ll a,ll b)
{
ll ans=1;
a%=mod;
while (b){
if (b&1) ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans%mod;
}
void NTT(int len,ll *a,int type)
{
for (int i=0; i
if (i
int nb=1;
for (int mid=1; mid
//ll wn=qpow(G,(mod-1)/(mid<<1));//原根代替单位根
//if (type==-1) wn=qpow(wn,mod-2);//逆变换要乘上逆元
ll wn=rt[type+1][nb++];
for (int j=0; j
ll w=1;
for (int k=0; k
ll x=a[j+k],y=w*a[j+k+mid]%mod;
a[j+k]=(x+y)%mod;
a[j+k+mid]=(x-y+mod)%mod;
}
}
}
}
int main(int argc, char const *argv[])
{
for (int i=0; i<=25; i++){//预处理出每个长度下的逆元
int len=1<
rt[2][i]=qpow(3,(mod-1)/len);//正变换
rt[0][i]=qpow(rt[2][i],mod-2);//逆变换
}
IOS;
cin.tie(0); cout.tie(0);
cin>>s1>>s2;
int len1=s1.length(),len2=s2.length();
for (int i=0; i
a[i]=s1[len1-i-1]-'0';
for (int i=0; i
b[i]=s2[len2-i-1]-'0';
int len=1,l=0;
while (len<=len1+len2) len<<=1,l++;
for (int i=0; i
r[i]=(r[i>>1]>>1)|((i&1)<
NTT(len,a,1); NTT(len,b,1);
for (int i=0; i
a[i]=(a[i]*b[i])%mod;
NTT(len,a,-1);
ll inv=qpow(len,mod-2);
for (int i=0; i<=len1+len2; i++)
a[i]=a[i]*inv%mod;
for (int i=0; i
if (a[i]>=10) {a[i+1]+=a[i]/10; a[i]%=10;}
}
int tail=len1+len2;
while (a[tail]==0 && tail>0) tail--;
while (a[tail]>=10) {a[tail+1]+=a[tail]/10; a[tail++]%=10;}
for (int i=tail; i>=0; i--)
printf("%d",a[i]);
printf("\n");
return 0;
}
标签:P1919,洛谷,10,--,ll,int,tail,include,mod
来源: https://www.cnblogs.com/lonely-wind-/p/13334058.html