QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#230060 | #7634. Cards | ucup-team1055# | AC ✓ | 13192ms | 16268kb | C++20 | 5.2kb | 2023-10-28 17:32:31 | 2023-10-28 17:32:31 |
Judging History
你现在查看的是测评时间为 2023-10-28 17:32:31 的历史记录
- [2023-10-28 19:27:18]
- hack成功,自动添加数据
- (//qoj.ac/hack/414)
- [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,我给组数据试试?
详细
Test #1:
score: 100
Accepted
time: 61ms
memory: 3700kb
input:
1 1 1 1 1 1 1
output:
399297742
result:
ok 1 number(s): "399297742"
Test #2:
score: 0
Accepted
time: 13165ms
memory: 16268kb
input:
100000 100000 1234 4567 7890 4321 54321
output:
348074135
result:
ok 1 number(s): "348074135"
Test #3:
score: 0
Accepted
time: 13192ms
memory: 16176kb
input:
100000 100000 1 2 3 4 5
output:
639188342
result:
ok 1 number(s): "639188342"
Test #4:
score: 0
Accepted
time: 13141ms
memory: 16140kb
input:
100000 100000 5 4 3 2 1
output:
211669278
result:
ok 1 number(s): "211669278"
Test #5:
score: 0
Accepted
time: 61ms
memory: 3864kb
input:
0 0 1 1 1 1 1
output:
1
result:
ok 1 number(s): "1"
Test #6:
score: 0
Accepted
time: 4162ms
memory: 6856kb
input:
1 50000 1 1 1 1 1
output:
548880636
result:
ok 1 number(s): "548880636"
Test #7:
score: 0
Accepted
time: 57ms
memory: 4040kb
input:
50000 1 1 1 1 1 1
output:
1
result:
ok 1 number(s): "1"
Test #8:
score: 0
Accepted
time: 11474ms
memory: 16256kb
input:
100000 100000 234 666 7655 12234 0
output:
45268602
result:
ok 1 number(s): "45268602"
Test #9:
score: 0
Accepted
time: 13145ms
memory: 16208kb
input:
99999 99999 12345 54332 12345 65432 34444
output:
360543661
result:
ok 1 number(s): "360543661"
Test #10:
score: 0
Accepted
time: 13154ms
memory: 16200kb
input:
99998 99998 1 1 1 1 1
output:
602326230
result:
ok 1 number(s): "602326230"
Test #11:
score: 0
Accepted
time: 13162ms
memory: 16076kb
input:
99998 99997 1 1 1 1 1
output:
159752985
result:
ok 1 number(s): "159752985"
Test #12:
score: 0
Accepted
time: 13180ms
memory: 16208kb
input:
99997 100000 1 2 3 4 5
output:
139603712
result:
ok 1 number(s): "139603712"
Test #13:
score: 0
Accepted
time: 13181ms
memory: 16056kb
input:
100000 99997 1 2 2 1 3232323
output:
363030953
result:
ok 1 number(s): "363030953"
Test #14:
score: 0
Accepted
time: 6ms
memory: 3692kb
input:
0 0 0 0 1 0 0
output:
1
result:
ok 1 number(s): "1"
Test #15:
score: 0
Accepted
time: 762ms
memory: 4732kb
input:
10000 10000 91095828 93770094 5303328 491263 50290308
output:
135900098
result:
ok 1 number(s): "135900098"
Test #16:
score: 0
Accepted
time: 729ms
memory: 4252kb
input:
9226 9995 62366139 253808 1929312 491263 4375669
output:
812662634
result:
ok 1 number(s): "812662634"
Test #17:
score: 0
Accepted
time: 643ms
memory: 4880kb
input:
18641 10000 1061 4359 1330 13764 16043
output:
112339046
result:
ok 1 number(s): "112339046"
Extra Test:
score: 0
Extra Test Passed