QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#230060#7634. Cardsucup-team1055#AC ✓13601ms16164kbC++205.2kb2023-10-28 17:32:312023-10-28 19:29:30

Judging History

你现在查看的是最新测评结果

  • [2023-10-28 19:29:30]
  • 自动重测本题所有获得100分的提交记录
  • 测评结果:AC
  • 用时:13601ms
  • 内存:16164kb
  • [2023-10-28 17:32:31]
  • 评测
  • 测评结果:100
  • 用时:13192ms
  • 内存:16268kb
  • [2023-10-28 17:32:31]
  • 提交

answer

//#pragma GCC optimize("O3,unroll-loops")
#include <bits/stdc++.h>

#define rep(i,s,n) for(int i = int(s); i < int(n); i++)
#define rrep(i,s,n) for(int i = int(n) - 1; i >= int(s); i--)
#define all(v) (v).begin(), (v).end()

using ll = long long;
using ld = long double;
using ull = unsigned long long;

template<class T>
bool chmin(T &a, T b) {
    if(a <= b) return false;
    a = b;
    return true;
}

template<class T>
bool chmax(T &a, T b) {
    if(a >= b) return false;
    a = b;
    return true;
}

using namespace std;

template <ll m> struct modint {
	using mint = modint;
	ll a; 
	modint(ll x = 0) : a((x % m + m) % m) {}
	static ll mod(){
		return m;
	}
	ll& val(){
		return a;
	}
	mint pow(ll n){
		mint res = 1;
		mint x = a;
		while (n){
			if (n & 1) res *= x;
			x *= x;
			n >>= 1;
		}
		return res;
	}
	mint inv(){
		return pow(m-2);
	}
	mint& operator+=(const mint rhs){
		a += rhs.a;
		if (a >= m) a -= m;
		return *this;
	}
	mint& operator-=(const mint rhs){
		if (a < rhs.a) a += m;
		a -= rhs.a;
		return *this;
	}
	mint& operator*=(const mint rhs){
		a = a * rhs.a % m;
		return *this;
	}
	mint& operator/=(mint rhs){
		*this *= rhs.inv();
		return *this;
	}
	friend mint operator+(const mint& lhs, const mint& rhs){
		return mint(lhs) += rhs;
	}
	friend mint operator-(const mint& lhs, const mint& rhs){
		return mint(lhs) -= rhs;
	}
	friend mint operator*(const mint& lhs, const mint& rhs){
		return mint(lhs) *= rhs;
	}
	friend mint operator/(const mint& lhs, const mint& rhs){
		return mint(lhs) /= rhs;
	}
	mint operator+() const {
		return *this;
	}
	mint operator-() const {
		return mint() - *this;
	}
};

using modint998244353 = modint<998244353>;
typedef modint998244353 mint;

struct ntt_info {
	static constexpr int rank2 = 23;
	const int g = 3;
	array<array<mint,rank2+1>, 2> root;
	ntt_info(){
		root[0][rank2] = mint(g).pow((mint::mod()-1)>>rank2);
		root[1][rank2] = root[0][rank2].inv();
		rrep(i,0,rank2){
			root[0][i] = root[0][i+1]*root[0][i+1];
			root[1][i] = root[1][i+1]*root[1][i+1];
		}
	}
};

int bit_reverse(int n, int bit_size){
	int rev = 0;
	rep(i,0,bit_size){
		rev |= ((n>>i)&1)<<(bit_size-i-1);
	}
	return rev;
}

void butterfly(vector<mint>&a, bool inverse){
	static ntt_info info;
	int n = a.size();
	int bit_size = 0;
	while((1<<bit_size)<n) bit_size++;
	assert(1<<bit_size == n);
	rep(i,0,n){
		int rev = bit_reverse(i, bit_size);
		if (i < rev){
			swap(a[i], a[rev]);
		}
	}
	rep(bit,0,bit_size){
		rep(i,0,n/(1<<(bit+1))){
			mint zeta1 = 1;
			mint zeta2 = info.root[inverse][1];
			mint w = info.root[inverse][bit+1];
			rep(j,0,1<<bit){
				int idx = i * (1<<(bit+1)) + j;
				int jdx = idx + (1<<bit);
				mint p1 = a[idx];
				mint p2 = a[jdx];
				a[idx] = p1 + zeta1 * p2;
				a[jdx] = p1 + zeta2 * p2;
				zeta1 *= w;
				zeta2 *= w; 
			}
		}
	}
	if (inverse){
		mint inv_n = mint(n).inv();
		rep(i,0,n) a[i] *= inv_n;
	}
}

vector<mint> convolution(const vector<mint> &f, const vector<mint> &g){
	int n = 1;
	while(n < int(f.size() + g.size() - 1)) n <<= 1;
	vector<mint> a(n), b(n);
	copy(f.begin(), f.end(), a.begin());
	copy(g.begin(), g.end(), b.begin());
	butterfly(a, false);
	butterfly(b, false);
	rep(i,0,n){
		a[i] *= b[i];
	}
	butterfly(a, true);
	a.resize(f.size() + g.size() - 1);
	return a;
}


mint naive(int n, int m, vector<mint> x){
	int k = n+2*m+1;
	vector<mint> dp(k);
	dp[n] = 1;
	vector<mint> v(5);
	mint sx = 0;
	rep(i,0,5){
		sx += x[i];
	}
	rep(i,0,5){
		v[i] = x[i] * sx.inv();
	}
	rep(num,0,m){
		vector<mint> ndp(k);
		rep(i,0,k){
			rep(j,0,5){
				if (i+j-2 >= 0 && i+j-2 < k) {
					ndp[i+j-2] += dp[i] * v[j];
				}
			}
		}
		dp = ndp;
	}
	mint ans = 0;
	rep(i,0,n+2*m+1){
		ans += dp[i];
	}
	return ans;
}

const int BORDER = 1500;

mint fast(int n, int m, vector<mint> x){
	int k = n+2*m+1;
	vector<mint> v(5);
	mint sx = 0;
	rep(i,0,5){
		sx += x[i];
	}
	rep(i,0,5){
		v[i] = x[i] * sx.inv();
	}

	auto nxt = [&](vector<mint> &dp) -> vector<mint> {
		vector<mint> ret((int)dp.size());
		rep(i,0,(int)dp.size()){
			if (dp[i].val() == 0) continue;
			rep(j,0,5){
				if (i+j-2 >= 0 && i+j-2 < (int)dp.size()) {
					ret[i+j-2] += dp[i] * v[j];
				}
			}
		}
		return ret;
	};

	vector<mint> dp(k);
	dp[n] = 1;
	vector<mint> g(4*BORDER+1);
	g[2*BORDER] = 1;
	rep(num,0,BORDER){
		g = nxt(g);
	}

	int sza = max(0,k-2*BORDER);
	int szb = min(k,2*BORDER);
	rep(num,0,m/BORDER){
		vector<mint> a(sza);
		vector<mint> b(szb);
		rep(i,0,sza){
			a[i] = dp[i+2*BORDER];
		}
		rep(i,0,szb){
			b[i] = dp[i];
		}
		if (sza>=1){
			a = convolution(a, g);
		}
		b.resize(szb+2*BORDER);
		rep(num,0,BORDER){
			b = nxt(b);
		}
		b.resize(k);
		a.resize(k);
		vector<mint> ndp(k);
		rep(i,0,k){
			ndp[i] = a[i] + b[i];
		}
		dp = ndp;
	}

	rep(num,(m/BORDER)*BORDER,m){
		dp = nxt(dp);
	}

	mint ans = 0;
	rep(i,0,k){
		ans += dp[i];
	}
	return ans;
}

int main(){
	int n, m; cin >> n >> m;
	vector<mint> x(5);
	rep(i,0,5){
		int z; cin >> z;
		x[i] = z;
	}
	//cout << naive(n, m, x).val() << '\n';
	cout << fast(n, m, x).val() << '\n';
}

这程序好像有点Bug,我给组数据试试?

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 58ms
memory: 3484kb

input:

1 1
1 1 1 1 1

output:

399297742

result:

ok 1 number(s): "399297742"

Test #2:

score: 0
Accepted
time: 13527ms
memory: 16116kb

input:

100000 100000
1234 4567 7890 4321 54321

output:

348074135

result:

ok 1 number(s): "348074135"

Test #3:

score: 0
Accepted
time: 13424ms
memory: 16080kb

input:

100000 100000
1 2 3 4 5

output:

639188342

result:

ok 1 number(s): "639188342"

Test #4:

score: 0
Accepted
time: 13533ms
memory: 16016kb

input:

100000 100000
5 4 3 2 1

output:

211669278

result:

ok 1 number(s): "211669278"

Test #5:

score: 0
Accepted
time: 62ms
memory: 3516kb

input:

0 0
1 1 1 1 1

output:

1

result:

ok 1 number(s): "1"

Test #6:

score: 0
Accepted
time: 4215ms
memory: 6876kb

input:

1 50000
1 1 1 1 1

output:

548880636

result:

ok 1 number(s): "548880636"

Test #7:

score: 0
Accepted
time: 59ms
memory: 3916kb

input:

50000 1
1 1 1 1 1

output:

1

result:

ok 1 number(s): "1"

Test #8:

score: 0
Accepted
time: 11848ms
memory: 16040kb

input:

100000 100000
234 666 7655 12234 0

output:

45268602

result:

ok 1 number(s): "45268602"

Test #9:

score: 0
Accepted
time: 13558ms
memory: 16164kb

input:

99999 99999
12345 54332 12345 65432 34444

output:

360543661

result:

ok 1 number(s): "360543661"

Test #10:

score: 0
Accepted
time: 13470ms
memory: 16068kb

input:

99998 99998
1 1 1 1 1

output:

602326230

result:

ok 1 number(s): "602326230"

Test #11:

score: 0
Accepted
time: 13486ms
memory: 16032kb

input:

99998 99997
1 1 1 1 1

output:

159752985

result:

ok 1 number(s): "159752985"

Test #12:

score: 0
Accepted
time: 13601ms
memory: 16076kb

input:

99997 100000
1 2 3 4 5

output:

139603712

result:

ok 1 number(s): "139603712"

Test #13:

score: 0
Accepted
time: 13462ms
memory: 16048kb

input:

100000 99997
1 2 2 1 3232323

output:

363030953

result:

ok 1 number(s): "363030953"

Test #14:

score: 0
Accepted
time: 6ms
memory: 3460kb

input:

0 0
0 0 1 0 0

output:

1

result:

ok 1 number(s): "1"

Test #15:

score: 0
Accepted
time: 776ms
memory: 4636kb

input:

10000 10000
91095828 93770094 5303328 491263 50290308

output:

135900098

result:

ok 1 number(s): "135900098"

Test #16:

score: 0
Accepted
time: 735ms
memory: 4100kb

input:

9226 9995
62366139 253808 1929312 491263 4375669

output:

812662634

result:

ok 1 number(s): "812662634"

Test #17:

score: 0
Accepted
time: 643ms
memory: 4736kb

input:

18641 10000
1061 4359 1330 13764 16043

output:

112339046

result:

ok 1 number(s): "112339046"

Extra Test:

score: 0
Extra Test Passed