蒟蒻全输出0求助
查看原帖
蒟蒻全输出0求助
370281
m256i楼主2022/5/17 19:13

RT,先上代码:

#include <cstdio>
#include <cctype>
#include <cstring>
#include <queue>
#include <bitset>
#include <algorithm>
typedef long long ll;
typedef unsigned long long ull;
int __ch;

template <typename T>
inline T max(T a, T b){return (a>b) ? a : b;}
template <typename T>
inline T min(T a, T b){return (a<b) ? a : b;}

namespace FastIO{
    template <typename T>
    void read(T &x){
        static char ch;
        x = 0;
        while (!isdigit(ch=getchar()));
        do x = (x*10)+(ch^'0');
        while (isdigit(ch=getchar()));
    }
    
    template <typename T>
    void write(T x, char c = ' '){
        static char st[100], *p;
        if (x == 0) putchar('0');
        for (p = st; x; x /= 10) *++p = x%10;
        for (; p != st; --p) putchar(*p|'0');
        putchar(c);
    }
    
    template <typename T>
    inline void writeln(T x){write(x, '\n');}
}

using namespace FastIO;

namespace Polynomial{
    using elem = ll;
    
    constexpr elem P = 75161927681LL, G = 3;
    constexpr elem MAXN = 1000006;
    
    // ================================================================ //
    
    struct Poly{
        int len;
        elem buf[MAXN<<2];
        inline void operator()(int len){this->len = len;}
        inline elem &operator[](size_t index){return buf[index];}
        inline elem *operator+(size_t index){return buf+index;}
    };
    
    constexpr elem pow(elem x, elem y){
        elem ans = 1;
        while (y){
            if (y&1) ans = (ans*x)%P;
            x = (x*x)%P;
            y >>= 1;
        }
        return ans;
    }
    
    constexpr elem pow128(__int128 x, __int128 y){
        __int128 ans = 1;
        while (y){
            if (y&1) ans = (ans*x)%P;
            x = (x*x)%P;
            y >>= 1;
        }
        return (elem)ans;
    }
    
    int _r[MAXN<<2], _rn, _invn;
    elem _w[30], _invw[30], _inv[MAXN];
    bool _hasinit;
    constexpr ll INVG = pow128(G, P-2);
    
    int getlim(int len){
        int lim = 1;
        while (lim < len) lim <<= 1;
        return lim;
    }
    
    void polyinit(int lim){
        if (_rn == lim) return;
        for (int i = 0; i < lim; ++i)
            _r[i] = ((_r[i>>1]>>1)|((i&1)?lim>>1:0));
    }
    
    void _initall(){
        if (_hasinit) return;
        for (int i = 0; i < 30; ++i)
            _w[i] = pow(G, (P-1)/(2<<i)), _invw[i] = pow(INVG, (P-1)/(2<<i));
        _hasinit = 1;
    }
    
    inline elem madd(elem x){return x<P?x:x-P;}
    inline elem msub(elem x){return x<0?x+P:x;}
    
    inline void clear(elem *begin, int cnt){
        memset(begin, 0, cnt*sizeof(elem));
    }
    
    inline void copy(elem *dest, const elem *src, int cnt){
        memcpy(dest, src, cnt*sizeof(elem));
    }
    
    inline void clear(Poly &poly, int cnt){clear(poly.buf, cnt);}
    inline void copy(Poly &dest, const Poly &src, int cnt){copy(dest.buf, src.buf, cnt);}
    
    void ntt(Poly &poly, int lim, bool opt){
        _initall(); polyinit(lim);
        int m;
        elem g, tmp, *w = opt?_w:_invw;
        for (int i = 0; i < lim; ++i)
            if (i<_r[i]) std::swap(poly[i], poly[_r[i]]);
        for (int k = 2; k <= lim; k <<= 1){
            m = k>>1;
            for (elem *i = poly.buf; i < poly.buf+lim; i += k){
                g = 1;
                for (elem *j = i; j < m+i; ++j){
                    tmp = *(m+j)*g%P;
                    *(m+j) = msub(*j-tmp);
                    *j = madd(*j+tmp);
                    g = *w*g%P;
                }
            }
            ++w;
        }
        if (!opt){
            elem inv = pow(lim, P-2);
            for (int i = 0; i < lim; ++i) poly[i] = poly[i]*inv%P;
        }
    }
    
    inline void dft(Poly &poly, int lim){ntt(poly, lim, 1);}
    inline void idft(Poly &poly, int lim){ntt(poly, lim, 0);}
    
    void polymul(Poly &dest, const Poly &src, int m=0){
        static Poly tmp;
        if (!m) m = dest.len+src.len;
        int len = min(m<<1, dest.len+src.len);
        int lim = getlim(len);
        copy(tmp, src, min(m, src.len));
        clear(tmp+len, lim-len);
        dft(dest, lim); dft(tmp, lim);
        for (int i = 0; i < lim; ++i) dest[i] = dest[i]*tmp[i]%P;
        idft(dest, lim);
        clear(dest+m, lim-m);
        dest.len = m;
    }
    
    void polyinv(Poly &dest, const Poly &src, int m=0){
        static Poly tmp;
        if (!m) m = src.len;
        if (m == 1){
            dest[0] = pow(src.buf[0], P-2); return;
        }
        polyinv(dest, src, (m+1)>>1);
        int lim = getlim(m<<1);
        copy(tmp, src, m);
        clear(tmp+m, lim-m);
        dft(dest, lim); dft(tmp, lim);
        for (int i = 0; i < lim; ++i)
            dest[i] = msub((2-tmp[i]*dest[i])%P)*dest[i]%P;
        idft(dest, lim);
        clear(dest+m, lim-m);
        dest.len = m;
    }
}

using namespace Polynomial;
Poly f, g;
// g=x/(1-x-x^2)

int main(){
    //freopen(".in", "r", stdin);
    //freopen(".out", "w", stdout);
    ll n;
    read(n); f(n+1);
    f[0] = 1, f[1] = -1, f[2] = -1;
    polyinv(g, f);
    f[0] = 0, f[1] = 1, f[2] = 0;
    polymul(g, f);
    printf("%lld.00", g[n]);
    
    
    return 0;
}

最初我写的是 P=2281701377P=2281701377,显然此时第五个点会 Wrong Answer。但当我使用更大的 7516192768175161927681 作为模数时,结果全部输出 00。请问是哪里溢出了?

(之前调 P1919 时也有一样的疑问,放在这里一并问吧)

2022/5/17 19:13
加载中...