Mys_C_K的数论方程好题

题目大意:
给定两个长为n的数列F和B,求长为n的数列x,使得 i   [ 1 , n ] , j = 1 n F ( g c d ( i , j ) )   x j = B i 在模998244353意义下成立。 n 10 5

题解:
考虑令 F ( n ) = d | n f ( d ) ,那么 f ( n ) = F ( n ) d | n , d n f ( d ) ,因此可以再 O ( n l g n ) 时间内通过 F ( n ) 求出 f ( n )
将题目中的F改写成f,有:
i   [ 1 , n ] , j = 1 n d | i , d | j f ( d )   x j = B i
i   [ 1 , n ] , d | i f ( d ) d | j n   x j = B i
x ( n ) = n | d x d ,那么 x n = x ( n ) n | d , n d x d ,因此知道x(n)后可以 O ( n l g n ) 时间内求出 x n
i   [ 1 , n ] , d | i f ( d ) x ( d ) = B i
i   [ 1 , n ] , d | i h ( d ) = b ( i )
根据上文结论,知道 b ( n ) 之后可以 O ( n l g n ) 时间内求出 h ( n ) ,进而求出 x ( n ) ,进而求出 x n
具体来说,以已知 F f ,代码大致如下:

for(int i=1;i<=n;i++) f[i]=F[i];
for(int i=1;i<=n;i++)
    for(int j=i<<1;j<=n;j++)
        f[j]-=f[i];

另一个同理。
代码:

// luogu-judger-enable-o2
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define N 100010
#define mod 998244353
#define lint long long
#define gc getchar()
using namespace std;
int f[N],x[N],fi[N];
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
inline int mol(int x) { return x%=mod,(x<0?x+=mod:x); }
inline int fast_pow(int x,int k=mod-2,int ans=1)
{   for(;k;k>>=1,x=(lint)x*x%mod) (k&1)?ans=(lint)ans*x%mod:0;return ans;   }
inline int getf(int *f,int n)
{
    for(int i=1;i<=n;i++)
        for(int j=i<<1;j<=n;j+=i) f[j]=mol(f[j]-f[i]);
    return 0;
}
inline int getg(int *g,int n)
{
    for(int i=n;i>=1;i--)
        for(int j=i<<1;j<=n;j+=i) g[i]=mol(g[i]-g[j]);
    return 0;
}
int main()
{
    int n=inn();
    for(int i=1;i<=n;i++) f[i]=inn();getf(f,n);
    for(int i=1;i<=n;i++) fi[i]=fast_pow(f[i]);
    for(int i=1;i<=n;i++) x[i]=inn();getf(x,n);
    for(int i=1;i<=n;i++) x[i]=(lint)x[i]*fi[i]%mod;
    getg(x,n);for(int i=1;i<=n;i++) printf("%d ",x[i]);
    return !printf("\n");
}

猜你喜欢

转载自blog.csdn.net/mys_c_k/article/details/80833762
MYS