結果
| 問題 |
No.215 素数サイコロと合成数サイコロ (3-Hard)
|
| コンテスト | |
| ユーザー |
potetisensei
|
| 提出日時 | 2019-10-01 01:50:13 |
| 言語 | C++11(廃止可能性あり) (gcc 13.3.0) |
| 結果 |
RE
(最新)
AC
(最初)
|
| 実行時間 | - |
| コード長 | 12,223 bytes |
| コンパイル時間 | 1,953 ms |
| コンパイル使用メモリ | 214,428 KB |
| 実行使用メモリ | 6,820 KB |
| 最終ジャッジ日時 | 2024-10-03 05:33:56 |
| 合計ジャッジ時間 | 2,710 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | RE * 2 |
コンパイルメッセージ
main.cpp: In member function ‘std::complex<double>& std::complex<double>::operator*=(const std::complex<_Tp>&) [with _Tp = double]’:
main.cpp:47:3: warning: no return statement in function returning non-void [-Wreturn-type]
46 | this->imag(a*d+b*c);
+++ |+ return *this;
47 | }
| ^
ソースコード
#pragma GCC target ("avx")
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <numeric>
#include <random>
#include <vector>
#include <array>
#include <bitset>
#include <queue>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <complex>
#include <x86intrin.h>
#define ALIGN __attribute__((aligned(32)))
using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
template<class T> using V = vector<T>;
template<class T> using VV = V<V<T>>;
constexpr ll TEN(int n) { return (n==0) ? 1 : 10*TEN(n-1); }
int bsr(int x) { return 31 - __builtin_clz(x); }
int bsr(ll x) { return 63 - __builtin_clzll(x); }
int bsf(int x) { return __builtin_ctz(x); }
int bsf(ll x) { return __builtin_ctzll(x); }
using C = complex<double>;
namespace std {
template<>
C& C::operator*=(const C& y) {
double a = this->real();
double b = this->imag();
double c = y.real();
double d = y.imag();
this->real(a*c-b*d);
this->imag(a*d+b*c);
}
}
template<class T>
T pow(T x, ll n, T r = 1) {
while (n) {
if (n & 1) r *= x;
x *= x;
n >>= 1;
}
return r;
}
template<uint MD>
struct ModInt {
uint v;
ModInt() : v{0} {}
ModInt(ll v) : v{normS(v%MD+MD)} {}
explicit operator bool() const {return v != 0;}
static uint normS(const uint &x) {return (x<MD)?x:x-MD;};
static ModInt make(const uint &x) {ModInt m; m.v = x; return m;}
static ModInt inv(const ModInt &x) {return pow(ModInt(x), MD-2);}
ModInt operator+(const ModInt &r) const {return make(normS(v+r.v));}
ModInt operator-(const ModInt &r) const {return make(normS(v+MD-r.v));}
ModInt operator*(const ModInt &r) const {return make((ull)v*r.v%MD);}
ModInt operator/(const ModInt &r) const {return *this*inv(r);}
ModInt& operator+=(const ModInt &r) {return *this=*this+r;}
ModInt& operator-=(const ModInt &r) {return *this=*this-r;}
ModInt& operator*=(const ModInt &r) {return *this=*this*r;}
ModInt& operator/=(const ModInt &r) {return *this=*this/r;}
};
template<uint MD> string to_string(ModInt<MD> m) {return to_string(m.v);}
using Mint = ModInt<TEN(9)+7>;
using R = double;
const R PI = 4*atan(R(1));
using Pc = C;
Pc polar(double r, double t) {
return Pc(cos(t)*r, sin(t)*r);
}
void fft(bool type, vector<Pc> &c) {
static vector<Pc> buf[30];
int N = int(c.size());
int s = bsr(N);
assert(1<<s == N);
if (!buf[s].size()) {
buf[s] = vector<Pc>(N);
for (int i = 0; i < N; i++) {
buf[s][i] = polar(1, i*2*PI/N);
}
}
vector<Pc> a = c, b(N);
for (int i = 1; i <= s; i++) {
int W = 1<<(s-i); //変更後の幅W
for (int y = 0; y < N/2; y += W) {
Pc now = buf[s][y]; if (type) now.imag(now.imag() * -1);
for (int x = 0; x < W; x++) {
auto l = a[y<<1 | x];
auto r = now * a[y<<1 | x | W];
b[y | x] = l+r;
b[y | x | N>>1] = l-r;
}
}
swap(a, b);
}
c = a;
}
template<class Mint>
vector<Mint> multiply(vector<Mint> x, vector<Mint> y) {
constexpr int B = 3, SHIFT = 10;
int S = x.size()+y.size()-1;
int N = 2<<bsr(S-1);
vector<Pc> a[B], b[B];
for (int fe = 0; fe < B; fe++) {
a[fe] = vector<Pc>(N);
b[fe] = vector<Pc>(N);
vector<Pc> c(N);
for (int i = 0; i < int(x.size()); i++) {
c[i].real((x[i].v >> (fe*SHIFT)) & ((1<<SHIFT)-1));
}
for (int i = 0; i < int(y.size()); i++) {
c[i].imag((y[i].v >> (fe*SHIFT)) & ((1<<SHIFT)-1));
}
fft(false, c);
for (int i = 0; i < N; i++) {
c[i] *= 0.5;
}
for (int i = 0; i < N; i++) {
int j = (N-i)%N;
a[fe][i] = Pc(c[i].real()+c[j].real(), c[i].imag()-c[j].imag());
b[fe][i] = Pc(c[i].imag()+c[j].imag(), -c[i].real()+c[j].real());
}
}
vector<Mint> z(S);
vector<Pc> c[B];
for (int fe = 0; fe < B; fe++) {
c[fe] = vector<Pc>(N);
}
for (int af = 0; af < B; af++) {
for (int bf = 0; bf < B; bf++) {
int cf = (af+bf)%B;
for (int i = 0; i < N; i++) {
if (af+bf<B) {
c[cf][i] += a[af][i]*b[bf][i];
} else {
c[cf][i] += a[af][i]*b[bf][i]*Pc(0, 1);
}
}
}
}
for (int fe = 0; fe < B; fe++) {
fft(true, c[fe]);
}
Mint base = 1;
for (int fe = 0; fe < 2*B-1; fe++) {
for (int i = 0; i < S; i++) {
if (fe < B) {
c[fe][i].real(c[fe][i].real() * 1.0/N);
z[i] += Mint(ll(round(c[fe][i].real())))*base;
} else {
c[fe-B][i].imag(c[fe-B][i].imag() * 1.0/N);
z[i] += Mint(ll(round(c[fe-B][i].imag())))*base;
}
}
base *= 1<<SHIFT;
}
return z;
}
template<class D>
struct Poly {
V<D> v;
int size() const {return int(v.size());}
Poly(int N = 0) : v(V<D>(N)) {}
Poly(const V<D> &v) : v(v) {shrink();}
Poly& shrink() {while (v.size() && !v.back()) v.pop_back(); return *this;}
D freq(int p) const { return (p < size()) ? v[p] : D(0); }
Poly operator+(const Poly &r) const {
int N = size(), M = r.size();
V<D> res(max(N, M));
for (int i = 0; i < max(N, M); i++) res[i] = freq(i)+r.freq(i);
return Poly(res);
}
Poly operator-(const Poly &r) const {
int N = size(), M = r.size();
V<D> res(max(N, M));
for (int i = 0; i < max(N, M); i++) res[i] = freq(i)-r.freq(i);
return Poly(res);
}
Poly operator*(const Poly &r) const {
int N = size(), M = r.size();
if (min(N, M) == 0) return Poly();
assert(N+M-1 >= 0);
V<D> res = multiply(v, r.v);
return Poly(res);
}
Poly operator*(const D &r) const {
V<D> res(size());
for (int i = 0; i < size(); i++) res[i] = v[i]*r;
return Poly(res);
}
Poly& operator+=(const Poly &r) {return *this = *this+r;}
Poly& operator-=(const Poly &r) {return *this = *this-r;}
Poly& operator*=(const Poly &r) {return *this = *this*r;}
Poly& operator*=(const D &r) {return *this = *this*r;}
Poly operator<<(const int n) const {
assert(n >= 0);
V<D> res(size()+n);
for (int i = 0; i < size(); i++) {
res[i+n] = v[i];
}
return Poly(res);
}
Poly operator>>(const int n) const {
assert(n >= 0);
if (size() <= n) return Poly();
V<D> res(size()-n);
for (int i = n; i < size(); i++) {
res[i-n] = v[i];
}
return Poly(res);
}
// x % y
Poly rem(const Poly &y) const {
return *this - y * div(y);
}
Poly rem_inv(const Poly &y, const Poly &ny, int B) const {
return *this - y * div_inv(ny, B);
}
Poly div(const Poly &y) const {
int B = max(size(), y.size());
return div_inv(y.inv(B), B);
}
Poly div_inv(const Poly &ny, int B) const {
return (*this*ny)>>(B-1);
}
// this * this.inv() = x^n + r(x) (size())
Poly strip(int n) const {
V<D> res = v;
res.resize(min(n, size()));
return Poly(res);
}
Poly rev(int n = -1) const {
V<D> res = v;
if (n != -1) res.resize(n);
reverse(begin(res), end(res));
return Poly(res);
}
// f * f.inv() = x^B + r(x) (B >= n)
Poly inv(int n) const {
int N = size();
assert(N >= 1);
assert(n >= N-1);
Poly c = rev();
Poly d = Poly(V<D>({D(1)/c.freq(0)}));
int i;
for (i = 1; i+N-2 < n; i *= 2) {
auto u = V<D>({2});
d = (d * (Poly(V<D>{2})-c*d)).strip(2*i);
}
return d.rev(n+1-N);
}
};
template<class D>
string to_string(const Poly<D> &p) {
if (p.size() == 0) return "0";
string s = "";
for (int i = 0; i < p.size(); i++) {
if (p.v[i]) {
s += to_string(p.v[i])+"x^"+to_string(i);
if (i != p.size()-1) s += "+";
}
}
return s;
}
// x^n % mod
template<class D>
Poly<D> nth_mod(ll n, const Poly<D> &mod) {
int B = mod.size() * 2 - 1;
Poly<D> mod_inv = mod.inv(B);
Poly<D> p = V<D>{Mint(1)};
int m = (!n) ? -1 : bsr(n);
for (int i = m; i >= 0; i--) {
if (n & (1LL<<i)) {
// += 1
p = (p<<1).rem_inv(mod, mod_inv, B);
}
if (i) {
// *= 2
p = (p*p).rem_inv(mod, mod_inv, B);
}
}
return p;
}
template<class D>
Poly<D> berlekamp_massey(const V<D> &s) {
int N = int(s.size());
V<D> b = {D(1)}, c = {D(1)};
D y = D(1);
for (int ed = 1; ed <= N; ed++) {
int L = int(c.size()), M = int(b.size());
D x = 0;
for (int i = 0; i < L; i++) {
x += c[i]*s[ed-L+i];
}
b.push_back(0); M++;
if (!x) {
continue;
}
D freq = x/y;
if (L < M) {
//use b
auto tmp = c;
c.insert(begin(c), M-L, D(0));
for (int i = 0; i < M; i++) {
c[M-1-i] -= freq*b[M-1-i];
}
b = tmp;
y = x;
} else {
//use c
for (int i = 0; i < M; i++) {
c[L-1-i] -= freq*b[M-1-i];
}
}
}
return Poly<D>(c);
}
const int MD = 610 * 13;
const int MC = 310;
const V<int> pd = {2, 3, 5, 7, 11, 13};
const V<int> cd = {4, 6, 8, 9, 10, 12};
struct StopWatch {
bool f = false;
clock_t st;
void start() {
f = true;
st = clock();
}
int msecs() {
assert(f);
return (clock()-st)*1000 / CLOCKS_PER_SEC;
}
};
int main() {
/* {
V<Mint> f = {1, 1, 2, 3};
cout << to_string(Poly<Mint>(f)) << endl;
cout << to_string(berlekamp_massey(f)) << endl;
}*/
ll n; int x, y;
cin >> n >> x >> y;
V<Mint> co(MD+1); co[0] = 1;
{
int c = x;
V<Mint> buf[6];
for (int i = 0; i < 6; i++) {
buf[i] = V<Mint>(MD);
buf[i][0] = 1;
}
for (int nc = 0; nc < c; nc++) {
for (int i = 0; i < 6; i++) {
for (int nw = MD-1; nw >= 0; nw--) {
buf[i][nw] = 0;
if (i) buf[i][nw] += buf[i-1][nw];
int d = pd[i];
if (nw < d) continue;
buf[i][nw] += buf[i][nw-d];
}
}
}
auto co2 = multiply(co, buf[5]);
co2.resize(co.size());
co = co2;
}
{
int c = y;
V<Mint> buf[6];
for (int i = 0; i < 6; i++) {
buf[i] = V<Mint>(MD);
buf[i][0] = 1;
}
for (int nc = 0; nc < c; nc++) {
for (int i = 0; i < 6; i++) {
for (int nw = MD-1; nw >= 0; nw--) {
buf[i][nw] = 0;
if (i) buf[i][nw] += buf[i-1][nw];
int d = cd[i];
if (nw < d) continue;
buf[i][nw] += buf[i][nw-d];
}
}
}
auto co2 = multiply(co, buf[5]);
co2.resize(co.size());
co = co2;
}
co[0] = -1;
auto rco = co;
reverse(begin(rco), end(rco));
auto pol = nth_mod(n, Poly<Mint>(rco));
V<Mint> buf(MD); buf[0] = 1;
V<Mint> sm(MD);
for (int i = 0; i < MD; i++) {
//v[i] * f
for (int j = 0; j < MD; j++) {
sm[j] += pol.freq(i)*buf[j];
}
for (int j = 1; j < MD; j++) {
buf[j] += buf[0]*co[j];
}
for (int j = 0; j < MD-1; j++) {
buf[j] = buf[j+1];
}
buf[MD-1] = 0;
}
Mint ans = 0;
for (int i = 0; i < MD; i++) {
ans += sm[i];
}
cout << ans.v << endl;
return 0;
}
potetisensei