Scx117
只一眼,便辽阔了时间。

题意:给你cd,每次询问的bip=998244353,求x数组(解方程)。

 

 

标程:

 1 #include<cstdio>
 2 using namespace std;
 3 typedef long long ll;
 4 const int mod=998244353,pmod=mod-1;
 5 const int N=100005;
 6 int n,c,d,q,I1[N],I2[N],b[N],a;
 7 inline int ksm(int x,int y) {
 8    int res=1; y=y%pmod+(y<0?pmod:0);
 9    while (y) {if (y&1) res=(ll)res*x%mod; x=(ll)x*x%mod; y>>=1;}
10    return res;
11 }
12 inline void mo_inv(int *a)//筛因数反演 
13 {
14     for (int i=1;i<=n;i++)
15       for (int j=2*i;j<=n;j+=i) a[j]=((ll)a[j]-a[i]+mod)%mod;
16 }
17 inline void mo_Inv(int *a)//筛倍数反演
18 {
19     for (int i=n;i>=1;i--)
20       for (int j=2*i;j<=n;j+=i) a[i]=((ll)a[i]-a[j]+mod)%mod;
21 }
22 int main()
23 {
24     scanf("%d%d%d%d",&n,&c,&d,&q);
25     for (int i=1;i<=n;i++) I1[i]=ksm(i,c-d),I2[i]=ksm(i,-d); 
26     mo_inv(I1);
27     for (int i=1;i<=n;i++) I1[i]=ksm(I1[i],-1);
28     while (q--)
29     {
30         for (int i=1;i<=n;i++) scanf("%d",&b[i]),b[i]=(ll)b[i]*I2[i]%mod;
31         mo_inv(b);int fl=0;
32         for (int i=1;i<=n;i++) {if (!I1[i]&&b[i]) {fl=1;break;}b[i]=(ll)b[i]*I1[i]%mod;}
33         if (fl) {puts("-1");continue;}
34         mo_Inv(b);
35         for (int i=1;i<=n;i++) printf("%d%c",(ll)b[i]*I2[i]%mod,(i==n)?10:32);
36     }
37     return 0;
38 }

 

易错点:1.被一个莫名其妙的卡时卡了10+

y=y%pmod+(y<0?pmod:0);这样写,用mod-1代替pmod都不行,不懂。注意负幂次需要+mod-1(费马小定理证明)

 

题解:莫比乌斯反演

套路是化简式子,换元,用mobius的形式代入(n=φ*1):

C,就是将n^a做反演。K亦然。求出S后(注意特判无解),发现从S推回A也是一个mobius反演的形式(不同的是枚举倍数)。于是一共做三次mobius反演即可,不用筛u(没有意义,筛u一般用于求sigma_i sigma_j [(i,j)=1]=sigma_i,j sigma d|i,d|j u(d),用欧拉筛枚举因数/倍数即可。时间复杂度O(qnlogn).

 

posted on 2018-03-31 22:09  Scx117  阅读(375)  评论(0编辑  收藏  举报