P5435 基於值域預處理的快速 GCD
阿新 • • 發佈:2022-12-10
思路
也就是將x分解成a * b * c,然後在分別與另一個數求解gcd
0-1000之內的gcd是可以直接預處理出來的,因為gcd(a,b) = gcd(a%b,b)(a>b)
為什麼不分解成兩個數呢,因為需要保證>1000的那個數一定是質數
程式碼
//基於值域的預處理 //也就是大事化小,小的又可以直接算 //將一個1e6的數華為幾個小的數,然後直接進行處理就可以了 #include <bits/stdc++.h> using namespace std; const int mod=998244353; using ll=long long; const int N=5005,M=1e6+5; vector<int>prime; bitset<M>st; int k[M][3],GCD[1005][1005]; void init(int n=1000,int m=1000000) { st[1]=1; k[1][0]=k[1][1]=k[1][2]=1; for(int i=2;i<=m;i++) { if(st[i]==0)prime.push_back(i),k[i][0]=1,k[i][1]=i; for(auto x:prime) { int y=x*i; if(y>m)break; st[y]=1; k[y][0]=k[i][0]*x; k[y][1]=k[i][1]; if(k[y][0]>k[y][1])swap(k[y][0],k[y][1]); if(i%x==0)break; } } for(int i=1;i<=n;i++)GCD[i][0]=GCD[0][i]=i; for(int i=1;i<=n;i++) for(int j=1;j<=i;j++) GCD[i][j]=GCD[j][i]=GCD[i%j][j]; } int gcd(int a,int b) { int ans=1,tmp; for(int i=0;i<=1;i++) { if(k[a][i]>1000) { if(b%k[a][i]==0)tmp=k[a][i]; else tmp=1; } else tmp=GCD[k[a][i]][b%k[a][i]]; b/=tmp; ans*=tmp; } return ans; } int a[N],b[N]; signed main() { init(); int n;cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; for(int i=1;i<=n;i++)cin>>b[i]; for(int i=1;i<=n;i++) { ll now=1,ans=0; for(int j=1;j<=n;j++) { now=now*i%mod; ans=(ans+now*gcd(a[i],b[j]))%mod; } cout<<ans<<endl; } return 0; }