acwing_gza's blog

Blogs

一个 QOJ#14016 Adjacent Add 的线性做法

2025-08-27 23:16:28 By acwing_gza

睁眼了一下怎么题解是 $O(n \log V)$ 的。

问题还是转化到给定 $X=\sum_{i=0}^{n}x_ik^i,Y=\sum_{i=0}^{n}y_ik^i$,需要判定 $X$ 是否是 $Y$ 的倍数,其中 $x_i=(-1)^{i-1}a_i,y_i=(-1)^i$。(1-index)

先 $|X| \to X$,$|Y| \to Y$。

如果 $X$ 是 $Y$ 的倍数,那么一定存在整数 $t$ 满足 $X=tY$。

容易发现因为 $a_i \leq 10^9$,所以 $t$ 最多最多也不超过 $10^9+O(k)$(反正代码里面把这个数当 $10^{10}$ 了干脆)。

我们取 $mod=10^{10}+19$(是个质数)求出模意义下的 $t$,然后把这个 $t$ 往回带入,如果这是答案,那就输出 Yes,否则就输出 No

正确性:如果存在一个 $t$ 满足答案,我们已知 $t < mod$ ,那么解出来的这个一定是答案。如果不存在,那么无论我们往回带什么整数都不可能符合条件,解出来的模意义 $t$ 也不例外。

upd:可以换成浮点数,直接算出 t——liuhengxi

赛场上的憋笑代码,写的有点丑:

#include<bits/stdc++.h>
using namespace std;
namespace gza{
    #define int __int128
    #define pb push_back
    #define MT int TTT=R;while(TTT--)
    #define pc putchar
    #define R read()
    #define fo(i,a,b) for(int i=a;i<=b;i++)
    #define rep(i,a,b) for(int i=a;i>=b;i--)
    #define m1(a,b) memset(a,b,sizeof a)
    namespace IO
    {
        inline int read()
        {
            int x=0;
            char ch=getchar();
            bool f=0;
            while(!isdigit(ch)){if(ch=='-') f=1;ch=getchar();}
            while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
            if(f) x=-x;
            return x;    
        }
        template<typename T> inline void write(T x)
        {
            if(x<0) pc('-'),x=-x;
            if(x>9) write(x/10);
            pc(x%10+'0');
        }
    };
    namespace math
    {
        inline int gcd(int a,int b)
        {
            int az=__builtin_ctz(a),bz=__builtin_ctz(b),z=(az>bz)?bz:az,t;
            b>>=bz;
            while(a) a>>=az,t=a-b,b=a,az=__builtin_ctz(t<0?-t:t),a=t<0?-t:t;
            return b<<z;
        }
        inline int qmi(int a,int b,int p)
        {
            int res=1;
            while(b)
            {
                if(b&1) res=res*a%p;
                a=a*a%p;
                b>>=1;
            }
            return res;
        }
        const int MAXN=2e6+10;
        int my_fac[MAXN],my_inv[MAXN];
        void init_binom(int mod)
        {
            my_fac[0]=1;fo(i,1,min(MAXN,mod)-1) my_fac[i]=my_fac[i-1]*i%mod;
            my_inv[min(MAXN,mod)-1]=qmi(my_fac[min(MAXN,mod)-1],mod-2,mod);rep(i,min(MAXN,mod)-2,0) my_inv[i]=my_inv[i+1]*(i+1)%mod;
        }
        int binom(int a,int b,int mod)
        {
            return my_fac[a]*my_inv[b]%mod*my_inv[a-b]%mod;
        }
    };
    using namespace IO;
    using namespace math;

    const int N=5e5+10;
    int n,k;
    int a[N];//a[i]->f
    int x,y;//xf+y
    vector<int> vx,vy;
    int nowx,nowy;
    mt19937 rnd(time(0));
    void solve()
    {
        n=R,k=R;
        fo(i,1,n) a[i]=R;
        x=0,y=0;
        vx.clear(),vy.clear();
        vx.resize(n),vy.resize(n);
        fo(i,1,n-1)
        {
            vx[i]=(i%2==1?1:-1);
            vy[i]=(i%2==1?-a[n-i]:a[n-i]);
        }
        vx[0]=-1,vy[0]=a[n];
        // for(auto i:vx) cout<<i<<' ';
        // cout<<endl;
        // for(auto i:vy) cout<<i<<' ';
        // cout<<endl;
        fo(i,0,n-2)
        {
            int tmp=(vx[i]%k+k)%k;
            int nd=(tmp-vx[i])/k;
            vx[i+1]-=nd,vx[i]+=nd*k;
        }
        fo(i,0,n-2)
        {
            int tmp=(vy[i]%k+k)%k;
            int nd=(tmp-vy[i])/k;
            vy[i+1]-=nd,vy[i]+=nd*k;
        }
        if(vx[n-1]<0) for(auto& i:vx) i=-i;
        int st=n-1;
        while(st&&vy[st]==0) st--;
        if(st==-1) return void(puts("No"));
        if(vy[st]<0) for(auto& i:vy) i=-i;
        int mod=10000000019;
        int tx=0,ty=0;
        rep(i,n-1,0) tx=(tx*k+vx[i])%mod;
        rep(i,n-1,0) ty=(ty*k+vy[i])%mod;
        int t=ty*qmi(tx,mod-2,mod)%mod;
        for(auto& i:vx) i*=t;
        fo(i,0,n-2)
        {
            int tmp=(vx[i]%k+k)%k;
            int nd=(tmp-vx[i])/k;
            vx[i+1]-=nd,vx[i]+=nd*k;
        }
        fo(i,0,n-2)
        {
            int tmp=(vy[i]%k+k)%k;
            int nd=(tmp-vy[i])/k;
            vy[i+1]-=nd,vy[i]+=nd*k;
        }
        fo(i,0,n-1) if(vx[i]!=vy[i]) return void(puts("No"));
        puts("Yes");
    }
    void main(){
        MT solve();
    }
}
signed main(){

    gza::main();
}

Comments

ChiFAN
大神呐
  • 2025-08-27 23:17:10
  • Reply
OldDriverTree
大神呐
  • 2025-08-28 10:34:34
  • Reply
liuhengxi
也可以不取模,用浮点数
  • 2025-08-31 23:10:50
  • Reply
tybbs_s
大神啊
  • 2025-09-16 19:50:11
  • Reply

Post a comment

You can refer to mike by using "@mike", and "mike" will be highlighted. If you want to type the character "@", please use "@@" instead.

You can enter "/kel" to use the emoticon "kel".