Sponsors

Codeforces Round #412 (rated, Div. 1, based on VK Cup 2017 Round 3), problem: (F) Test Data Generation, Accepted Solution In C/C++

#include<bits/stdc++.h>
#define ll long long

ll multmod(ll a, ll b, ll moder){
 a = (a % moder + moder) % moder, b = (b % moder + moder) % moder;
 ll ret = 0;
 for ( ; b; b >>= 1){
 if (b & 1){
 ret = ret + a >= moder ? ret + a - moder : ret + a;
 }
 a = a << 1 > moder ? (a << 1) - moder : a << 1;
 }
 return ret;
}

template <typename T> 
class modequa{
private:
 T remain, moder;
 
public:
 modequa <T>(){}
 modequa <T>(T remain, T moder) : remain(remain), moder(moder){}
 T getremain(){return remain;}
 T getmoder(){return moder;}
 
 void setvalue(T remain, T moder){
 this -> remain = remain;
 this -> moder = moder;
 }
 
 modequa <T> crt(const modequa <T> &p){
 T gcd = moder, x = 1, y = 0;
 for (T b = p.moder, x1 = 0, y1 = 1, r, s; b; ){
 r = x, s = y;
 x = x1, y = y1, x1 = r - x1 * (gcd / b), y1 = s - y1 * (gcd / b);
 r = gcd % b, gcd = b, b = r;
 }
 if ((p.remain - remain) % gcd) return modequa <T>(0, 0);
 T lcm = moder / gcd * p.moder;
 T ans = (p.remain - remain) / gcd;
 ans = multmod(multmod(ans, x, lcm), moder, lcm);
 ans += remain;
 ans += ans < 0 ? lcm : ans >= lcm ? -lcm : 0;
 return modequa <T>(ans, lcm);
 }
};

// Èç¹ûÄ£Êý²»ÊÇÖÊÊý£¬ÄÇô»ù±¾¾ÍÖ»ÄÜ×ö¼Ó¼õ³ËºÍÇóµ¼ÁËorz 
class poly{
private:
 int *a;
 int length, size;
 int moder, root, invroot;
 // ³£ÓõÄÁ½×éÄ£ÊýΪ ((119 << 23) + 1, 3, 332748118) ºÍ ((479 << 21) + 1, 3, 334845270)

 int powermod(int a, int exp, int moder)const &{
 int ret = 1;
 for ( ; exp; exp >>= 1){
 if (exp & 1){
 ret = 1ll * a * ret % moder;
 }
 a = 1ll * a * a % moder;
 }
 return ret;
 }
 
 void NTT(int *a, int length, int type, int moder, int root)const &{
 int len = -1;
 for (int x = length; x; ++ len, x >>= 1);
 for(int i = 1, j = 0; i < length - 1; ++ i){
 for(int s = length; j ^= s >>= 1, ~j & s; );
 if(i < j){
 std::swap(a[i], a[j]);
 }
 }
 for (int i = 1; i <= len; ++ i){
 int unit = powermod(root, moder - 1 >> i, moder);
 for (int j = 0; j < length; j += 1 << i){
 int w = 1;
 for (int k = j, szk = 1 << i - 1; k < j + szk; ++ k){
 int s = a[k], t = 1ll * w * a[k + szk] % moder;
 a[k] = s + t >= moder ? s + t - moder : s + t;
 a[k + szk] = s - t < 0 ? s - t + moder : s - t;
 w = 1ll * w * unit % moder;
 }
 }
 }
 if (type == 1) return;
 int inv = powermod(length, moder - 2, moder);
 for (int i = 0; i < length; ++ i){
 a[i] = 1ll * a[i] * inv % moder;
 }
 }
 
 void apply(int size){
 if (!size) return;
 a = new int [size]();
 this -> size = size;
 }
 
 void destroy(){
 if (!size) return;
 delete [] a;
 a = nullptr;
 }
 
 void resize(int size){
 if (!size) return;
 int *aux = a;
 a = new int [size]();
 memcpy(a, aux, sizeof(int) * (length + 1));
 if (this -> size) delete [] aux;
 this -> size = size;
 }

public:
 poly() : length(-1), moder(0), root(0), invroot(0){a = nullptr;}
 // Èç¹ûÄ£Êý·ÇNTTÖÊÊý root ºÍ invroot Ëæ±ãÉè¾ÍºÃÀ±~ 
 poly(int length, int moder, int root, int invroot):length(length), moder(moder), root(root), invroot(invroot){apply(length + 2 << 1);}
 poly(const poly &p):length(p.length), moder(p.moder), root(p.root), invroot(p.invroot){apply(p.size); memcpy(a, p.a, sizeof(int) * (p.length + 1));}
 poly(const poly &p, int length):length(length), moder(p.moder), root(p.root), invroot(p.invroot){apply(length + 2 << 1); memcpy(a, p.a, sizeof(int) * (std::min(length, p.length) + 1));}
 ~poly(){destroy();}
 void clear(){destroy(); length = -1, size = moder = root = invroot = 0;}
 int &operator [](int n){return a[n];}
 int getlength(){return length;}
 void setmoder(int moder, int root, int invroot){this -> moder = moder, this -> root = root, this -> invroot = invroot;}
 int getmoder(){return moder;}
 
 void setlength(int length){
 if (length >= size) resize(length + 2 << 1);
 if (length >= this -> length){
 this -> length = length;
 return;
 }
 memset(a + length + 1, 0, sizeof(int) * (this -> length - length));
 this -> length = length;
 }
 
 poly &operator = (const poly &p){
 destroy();
 apply(p.size);
 length = p.length;
 moder = p.moder;
 root = p.root;
 invroot = p.invroot;
 memcpy(a, p.a, sizeof(int) * (length + 1));
 return *this;
 }
 
 // Ï൱ÓÚ³ËÒÔ x ^ dis
 poly operator << (const int &dis)const &{
 poly ret(length + dis, moder, root, invroot);
 memcpy(ret.a + dis, a, sizeof(double) * (length + 1));
 return ret;
 }
 
 // Ï൱ÓÚ³ýÒÔ x ^ dis
 poly operator >> (const int &dis)const &{
 if (dis > length) return poly(-1, moder, root, invroot);
 poly ret(length - dis, moder, root, invroot);
 memcpy(ret.a, a + dis, sizeof(int) * (ret.length + 1));
 return ret;
 }
 
 int value(int x){
 int now = 1, ret = 0;
 for (int i = 0; i <= length; ++ i){
 ret = (ret + 1ll * a[i] * now) % moder;
 now = 1ll * now * x % moder;
 }
 return ret;
 }
 
 poly operator + (const poly &p)const &{
 if (!~length) return p;
 if (!~p.length) return *this;
 poly ret(*this, std::max(length, p.length));
 for (int i = 0; i <= p.length; ++ i){
 ret.a[i] += p.a[i];
 ret.a[i] -= ret.a[i] >= moder ? moder : 0;
 }
 for ( ; ~ret.length && !ret.a[ret.length]; -- ret.length)
 ;
 return ret;
 }
 
 poly operator - (const poly &p)const &{
 if (!~length) return p;
 if (!~p.length) return *this;
 poly ret(*this, std::max(length, p.length));
 for (int i = 0; i <= p.length; ++ i){
 ret.a[i] -= p.a[i];
 ret.a[i] += ret.a[i] < 0 ? moder : 0;
 }
 for ( ; ~ret.length && !ret.a[ret.length]; -- ret.length)
 ;
 return ret;
 }
 
 poly operator - ()const &{
 poly ret(length, moder, root, invroot);
 for (int i = 0; i <= length; ++ i){
 ret.a[i] = a[i] ? moder - a[i] : 0;
 }
 return ret;
 }
 /*&
 poly operator * (const poly &p)const &{
 if (!~length || !~p.length) return poly(-1, moder, root, invroot);
 int n = length + p.length;
 int lengthret = 1;
 for ( ; lengthret <= n; lengthret <<= 1)
 ;
 int *aux = new int [lengthret]();
 int *aux1 = new int [lengthret]();
 memcpy(aux, a, sizeof(int) * (length + 1));
 memcpy(aux1, p.a, sizeof(int) * (p.length + 1));
 NTT(aux, lengthret, 1, moder, root);
 NTT(aux1, lengthret, 1, moder, root);
 for (int i = 0; i < lengthret; ++ i){
 aux[i] = 1ll * aux[i] * aux1[i] % moder;
 }
 NTT(aux, lengthret, -1, moder, invroot);
 poly ret(n, moder, root, invroot);
 memcpy(ret.a, aux, sizeof(int) * (n + 1));
 delete [] aux;
 delete [] aux1;
 return ret;
 }*/
 
 ///*-------------------- ÕâÊÇÄ£Êý·ÇNTTÖÊÊýµÄÄ£°å£¬Çë°´ÐèÈ¡ÓÃ~ ------------------------------
 poly operator *(const poly &p)const &{
 const int multmoder[2] = {(119 << 23) + 1, (479 << 21) + 1};
 const int multroot[2] = {3, 3};
 const int multinvroot[2] = {332748118, 334845270};
 if (!~length || !~p.length) return poly(-1, moder, root, invroot);
 int n = length + p.length;
 int lengthret = 1;
 for ( ; lengthret <= n; lengthret <<= 1)
 ;
 int *aux = new int [lengthret]();
 int *aux1 = new int [lengthret]();
 int *aux2 = new int [lengthret]();
 memcpy(aux, a, sizeof(int) * (length + 1));
 memcpy(aux2, p.a, sizeof(int) * (p.length + 1));
 NTT(aux, lengthret, 1, multmoder[0], multroot[0]);
 NTT(aux2, lengthret, 1, multmoder[0], multroot[0]);
 for (int i = 0; i < lengthret; ++ i){
 aux[i] = 1ll * aux[i] * aux2[i] % multmoder[0];
 }
 NTT(aux, lengthret, -1, multmoder[0], multinvroot[0]);
 memcpy(aux1, a, sizeof(int) * (length + 1));
 memset(aux2, 0, sizeof(int) * lengthret);
 memcpy(aux2, p.a, sizeof(int) * (p.length + 1));
 NTT(aux1, lengthret, 1, multmoder[1], multroot[1]);
 NTT(aux2, lengthret, 1, multmoder[1], multroot[1]);
 for (int i = 0; i < lengthret; ++ i){
 aux1[i] = 1ll * aux1[i] * aux2[i] % multmoder[1];
 }
 NTT(aux1, lengthret, -1, multmoder[1], multinvroot[1]);
 poly ret(n, moder, root, invroot);
 for(int i = 0; i <= n; ++ i){
 modequa <ll> equa(aux[i], multmoder[0]), equb(aux1[i], multmoder[1]);
 ret.a[i] = equa.crt(equb).getremain() % moder;
 }
 delete [] aux;
 delete [] aux1;
 delete [] aux2;
 return ret;
 }
 //----------------------------------------------------------------------------------------*/
 
 poly operator * (const int &p)const &{
 int q = (p % moder + moder) % moder;
 if (!q) return poly(-1, moder, root, invroot);
 poly ret(length, moder, root, invroot);
 for (int i = 0; i <= length; ++ i){
 ret.a[i] = 1ll * a[i] * q % moder;
 }
 return ret;
 }
 
 friend poly operator * (const int &q, const poly &p){return p * q;}
 poly &operator += (const poly &p){*this = *this + p; return *this;}
 poly &operator -= (const poly &p){*this = *this - p; return *this;}
 poly &operator *= (const poly &p){*this = *this * p; return *this;}
 poly &operator *= (const int &p){*this = *this * p; return *this;}
};

const int N = 100;

int maxn, maxa, moder;
int q[N];

int main(){
 scanf("%d%d%d", &maxn, &maxa, &moder);
 if (maxa == 1){
 return printf("0\n"), 0;
 }
 int cnt = 0;
 for (maxa >>= 1; maxa; maxa >>= 1){
 q[cnt ++] = maxa;
 }
 std::reverse(q, q + cnt);
 int ans = 1;
 poly a(maxn, moder, 0, 0);
 poly b(maxn, moder, 0, 0);
 a[0] = 1;
 b[1] = 1;
 for (int i = 0; i < cnt - 1; ++ i){
 poly ret1(a);
 ret1 = (ret1 + b) * (q[i] & 1 ? b : a);
 if (q[i] & 1 ? b[0] : a[0]){
 ret1 -= b;
 }
 else{
 ret1 += a;
 }
 ret1.setlength(maxn);
 poly ret2(a);
 ret2 = (ret2 + b) * (q[i] & 1 ? a : b);
 if (q[i] & 1 ? a[0] : b[0]){
 ret2 -= a;
 }
 else{
 ret2 += b;
 }
 ret2.setlength(maxn);
 if (q[i + 1] & 1){
 a = ret1;
 for (int i = 1; i <= maxn; ++ i){
 b[i] = (ret2[i] + ret1[i - 1] + ret2[i - 1]) % moder;
 }
 }
 else{
 a = ret1;
 b = ret2;
 }
 for (int i = 1; i <= maxn; i += 2){
 ans = (ans + b[i]) % moder;
 }
 }
 return printf("%d\n", ans), 0;
}

Fobi AI Announces Partial...

Fobi AI Secures Partial Revocation Order, Launches Strategic Private...

Beautiful AI-Generated Alloy of...

AI-Generated "Pretty" Aloy Sparks Predictable Fury Across Social Media The...

Do GloFish glow under...

Do GloFish Glow Under Black Light? Unveiling the Fluorescent...

NASCAR Trial Intensifies As...

NASCAR Trial Heats Up as Jim France and Richard...

Google previews upcoming Android...

Google Unveils Android XR Smart Glasses Powered by Gemini...

Who has the most...

The Cash Kings: Who Holds the World's Most Liquid...

Fobi AI Announces Partial Revocation Order and Non-Brokered Private Placement

Fobi AI Secures Partial Revocation Order, Launches Strategic Private Placement VANCOUVER, BC – Fobi AI Inc. (TSXV: FOBI) (Pink: FOBIF), a leading provider of real-time...

Beautiful AI-Generated Alloy of Horizon Zero Dawn Attracts the Usual Ire

AI-Generated "Pretty" Aloy Sparks Predictable Fury Across Social Media The intersection of fan art, AI generation, and hotly debated video game character design erupted once...

Do GloFish glow under black light?

Do GloFish Glow Under Black Light? Unveiling the Fluorescent Secret The aquarium world is full of dazzling colors, but few sights are as mesmerizing as...

NASCAR Trial Intensifies As Jim France And Richard Childress Testify

NASCAR Trial Heats Up as Jim France and Richard Childress Face the Court The high-stakes legal battle surrounding NASCAR’s governance and team economics reached a...

Google previews upcoming Android XR smart glasses equipped with Gemini

Google Unveils Android XR Smart Glasses Powered by Gemini AI Google LLC is pulling back the curtain on its long-awaited foray into the next generation...

Who has the most liquid cash?

The Cash Kings: Who Holds the World's Most Liquid Assets? In the high-stakes world of global finance, the question of "Who has the most liquid...

Los Angeles partners kick off “Grow the Game of Soccer” free clinic series aimed at empowering youth sports

Los Angeles Kicks Off Major Initiative to 'Grow the Game of Soccer' Ahead of World Cup 2026 The spirit of the 2026 FIFA World Cup...

Trump signs off on nationwide vaccine schedule review as CDC withdraws infant Hep B guidance: ‘Fast track’

Trump Initiates Nationwide Review of Pediatric Vaccine Schedule Following CDC Guidance Withdrawal In a significant move that thrusts public health policy back into the national...

Supreme Court Puts Trump’s Midterm Power Grab Back on Track

Supreme Court Puts Trump-Backed Texas Power Grab Back on Track The political landscape ahead of the 2022 midterm elections just shifted dramatically, thanks to a...