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=2281701377,显然此时第五个点会 Wrong Answer。但当我使用更大的 75161927681 作为模数时,结果全部输出 0。请问是哪里溢出了?
(之前调 P1919 时也有一样的疑问,放在这里一并问吧)