how to run faster

题目大意:

已知 $$ b_i = \sum_{j=1}^n {(i,j)^d [i,j]^c x_j}$$,给定 $b_i$ 求解 $x_i$

解法:


考虑 $f(n) = \sum_{d|n}{fr(d)}$,这样有 $$\sum_{t|i}{fr(t) \sum_{t|j}{j^d x_j}  }  = b_i$$

容斥得 $fr(i) \sum_{i|j}{j^d x_j}$ 其中 $fr(n)$ 可以容斥得到,再次容斥得到 $x_i$

注意在除以 $fr(i)$ 时会产生无解,多解的情况。

#include <bits/stdc++.h>

#define LL long long
#define LD double
#define FOR(i,a,b) for (int i = (a);i <= (b); i++)
#define DFOR(i,a,b) for (int i = (a);i >= (b); i--)
#define debug(x) cerr << "debug: " << (#x) << " = " << (x) <<endl;
#define PI acos(-1)
#define mp make_pair
#define pb push_back
#define itr iterator
#define bit(x) (1LL<<(x))
#define lb(x) ((x)&(-x))
#define sqr(x) ((x)*(x))
#define gn 3
#define l(x) ch[x][0]
#define r(x) ch[x][1]
#define y0 Y0
#define y1 Y1
#define y2 Y2
#define fir first
#define sec second

using namespace std;

const int N = 300010;
const LL P = 998244353ll;

LL Cc,Dd,fr[N],z[N];

LL qpow(LL x,int n)
{
    LL ans=1;
    for(;n;n>>=1,x=x*x%P) if(n&1) ans=ans*x%P;
    return ans;
}

int main()
{
    int n,q;
    cin >> n >> Cc >> Dd >> q;
    FOR(i,1,n) fr[i] = qpow(i,(Cc-Dd+P-1)%(P-1));
    FOR(i,1,n) for(int j=i+i;j<=n;j+=i) fr[j] = (fr[j]+P-fr[i])%P;
    while(q--)
    {
        FOR(i,1,n)
        {
            scanf("%lld",&z[i]);
            z[i] = z[i] * qpow(qpow(i,Dd), P-2)%P;
        }
        FOR(i,1,n) for(int j=i+i;j<=n;j+=i) z[j] = (z[j]+P-z[i])%P;
        bool nosol = 0,mulsol = 0;
        FOR(i,1,n)
        {
            if(fr[i]==0 && z[i]!=0) nosol = 1;
            else if(fr[i]==0 && z[i]==0) mulsol = 1;
            z[i] = z[i] * qpow(fr[i],P-2)%P;
            
        }
        DFOR(i,n,1) for(int j=i+i;j<=n;j+=i) z[i] = (z[i]+P-z[j])%P;
        if(nosol) puts("-1");
        else
        {    
            FOR(i,1,n) z[i] = z[i] * qpow(qpow(i,Dd),P-2)%P;
            FOR(i,1,n) printf("%lld ",z[i]);
            printf("\n");
        }
    }
    return 0;
}
View Code

 

posted @ 2017-09-04 16:34  lawyer'  阅读(173)  评论(0编辑  收藏  举报