QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#801566#9798. Safety Firstucup-team135TL 2982ms728648kbC++2010.8kb2024-12-07 02:30:022024-12-07 02:30:03

Judging History

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

  • [2024-12-07 02:30:03]
  • 评测
  • 测评结果:TL
  • 用时:2982ms
  • 内存:728648kb
  • [2024-12-07 02:30:02]
  • 提交

answer

#include <bits/stdc++.h>

using namespace std;
mt19937 rnd;
#define app push_back
#define all(x) (x).begin(),(x).end()
#ifdef LOCAL
#define debug(...) [](auto...a){ ((cout << a << ' '), ...) << endl;}(#__VA_ARGS__, ":", __VA_ARGS__)
#define debugv(v) do {cout<< #v <<" : {"; for(int izxc=0;izxc<v.size();++izxc) {cout << v[izxc];if(izxc+1!=v.size()) cout << ","; }cout <<"}"<< endl;} while(0)
#else
#define debug(...)
#define debugv(v)
#endif
#define lob(a,x) lower_bound(all(a),x)
#define upb(a,x) upper_bound(all(a),x)
const int MOD = 998244353;
const long long MOD2 = (long long) MOD * MOD;
const int root = 3;
const int alim = 64; // Bound for using O(n^2) polynomial mult

int modpow(int b, int e) {
	int ans = 1;
	for (; e; b = (long long) b * b % MOD, e /= 2)
		if (e & 1) ans = (long long) ans * b % MOD;
	return ans;
}

const int MODinv = 2 - MOD; // pow(-MOD, -1, 2**32)
inline int m_reduce(long long x) {
  int m = x * MODinv;
  return (x>>32) - (((long long) m * MOD) >> 32);
}

const int r2 = modpow(2, 64);
inline int m_transform(int x) {
  return m_reduce((long long)x * r2);
}

inline int m_add(int x, int y) {
  int z = x + y;
  return z < 0 ? z + MOD : z - MOD;
}

inline int m_sub(int x, int y) {
  int z = x - y;
  return z < 0 ? z + MOD : z - MOD;
}

inline int m_mult(int x, int y) {
  return m_reduce((long long) x * y);
}

vector<int> rt = {1};
vector<int> transformed_rt;
vector<int> transformed_rt2;

template<int a>
void transform(vector<int> &P) {
  int m = P.size();
  int n = m / a;

  int size = rt.size();
  while (2 * size < n) {
    rt.resize(n / 2);
    int r = modpow(root, MOD / (4 * size));
    for (int i = 0; i < size; ++i)
      rt[i + size] = (long long) r * rt[i] % MOD;
    size *= 2;
  }

  // For montgomery
  for (int i = transformed_rt.size(); i < rt.size(); ++i) {
    transformed_rt.resize(rt.size());
    transformed_rt[i] = m_transform(rt[i]);
    transformed_rt2.resize(rt.size());
    transformed_rt2[i] = (unsigned int) MODinv * transformed_rt[i];
  }

  int k = n;
  while (k >= 4) k /= 4;

  if (k == 2) {
    int step = n * a;
    int half_step = step / 2;
    for (int j1 = 0; j1 < half_step; ++j1) {
      int j2 = j1 + half_step;

      int diff = m_sub(P[j1], P[j2]);
      P[j1] = m_add(P[j1], P[j2]);
      P[j2] = diff;
    }
    k = n/2;
  } else {
    k = n;
  }

  for (; k > 1; k /= 4) {
    for (int i = 0; i < n/k; ++i) {
      int step = k * a;
      int half_step = step / 2;
      int quarter_step = half_step / 2;

      int R20  = transformed_rt2[2 * i];
      int RR0 = transformed_rt[2 * i];

      int R21 = transformed_rt2[2 * i + 1];
      int RR1 = transformed_rt[2 * i + 1];

      int R2 = transformed_rt2[i];
      int RR = transformed_rt[i];

      int j1 = i * step;
      int j2 = j1 + quarter_step;
      int j3 = j2 + quarter_step;
      int j4 = j3 + quarter_step;

      for (int j = 0; j < quarter_step; ++j, ++j1, ++j2, ++j3, ++j4) {
        int z0;
        {
          int z = P[j3];
          int m = (unsigned int) R2 * z;
          z0 = ((long long) z * RR - (long long) m * MOD) >> 32;
        }

        int z1;
        {
          int z = P[j4];
          int m = (unsigned int) R2 * z;
          z1 = ((long long) z * RR - (long long) m * MOD) >> 32;
        }

        int sum0 = m_add(P[j1], z0);
        int diff0 = m_sub(P[j1], z0);
        int sum1 = P[j2] + z1;
        int diff1 = P[j2] - z1;

        // [sum0, sum1, diff0, diff1]

        int zz0;
        {
          int z = sum1;
          int m = (unsigned int) R20 * z;
          zz0 = ((long long) z * RR0 - (long long) m * MOD) >> 32;
        }

        int zz1;
        {
          int z = diff1;
          int m = (unsigned int) R21 * z;
          zz1 = ((long long) z * RR1 - (long long) m * MOD) >> 32;
        }

        P[j1]  = m_add(sum0, zz0);
        P[j2]  = m_sub(sum0, zz0);
        P[j3]  = m_add(diff0, zz1);
        P[j4]  = m_sub(diff0, zz1);
      }
    }
  }

  for (int i = 0; i < m; ++i)
    if (P[i] < 0) P[i] += MOD;
}

template<int a>
void inverse_transform(vector<int> &P) {
  int m = P.size();
  int n = m / a;
  int n_inv = m_transform(modpow(n, MOD - 2));

  vector<int> rev(n);
  for (int i = 1; i < n; ++i) {
    rev[i] = rev[i / 2] / 2 + (i & 1) * n / 2;
  }

  // P = [p * n_inv for p in P]
  for (int i = 0; i < m; ++i)
    P[i] = m_mult(n_inv, P[i]);

  // P = [P[a * rev[i // a] + (i % a)] for i in range(m)]
  for (int i = 1; i < n; ++i)
    if (i < rev[i])
      swap_ranges(P.begin() + a * i, P.begin() + a * i + a, P.begin() + a * rev[i]);

  // P = [P[-a * (i // a) + (i % a)] for i in range(m)]
  for (int i = 1; i < n/2; ++i)
    swap_ranges(P.begin() + a * i, P.begin() + a * i + a, P.begin() + a * (n - i));

  transform<a>(P);

  // P = [P[a * rev[i // a] + (i % a)] for i in range(m)]
  for (int i = 1; i < n; ++i)
    if (i < rev[i])
      swap_ranges(P.begin() + a * i, P.begin() + a * i + a, P.begin() + a * rev[i]);
}

template<int a>
void fast_polymult_mod(vector<int> &P, vector<int> &Q) {
  int m = P.size();
  int n = m / a;

  transform<a>(P);
  transform<a>(Q);

  vector<int> &PQ = P;
  for (int i = 0; i < n; ++i) {
    vector<unsigned long long> res(2 * a);
    for (int j = 0; j < a; ++j) {
      if (j >= 10 && j % 9 == 8)
        for (int k = j; k < j + a - 10; ++k)
          res[k] -= (res[k] >> 63) * 9 * MOD2;
      for (int k = 0; k < a; ++k)
        res[j + k] += (long long) P[i * a + j] * Q[i * a + k];
    }

    int c = rt[i/2];
    if (i & 1) c = MOD - c;
    for (int j = 0; j < a; ++j)
      PQ[i * a + j] = (res[j] + c * (res[j + a] % MOD)) % MOD;
  }

  inverse_transform<a>(PQ);
}

template <size_t... N>
void work(std::index_sequence<N...>, int x, std::vector<int>& a, std::vector<int>& b) {
  static void (*ptrs[])(std::vector<int>&, std::vector<int>&) = {&fast_polymult_mod<N+1>...};
  ptrs[x - 1](a, b);
}

void fast_polymult(vector<int> &P, vector<int> &Q) {
  int m1 = P.size();
  int m2 = Q.size();
  int res_len = m1 + m2 - 1;

  int b = 1;
  while ((alim << b) < res_len) ++b;
  int a = ((res_len - 1) >> b) + 1;
  int m = a << b;

  P.resize(m);
  Q.resize(m);

  // Call fast_polymult_mod<a>(P, Q);
  work(std::make_index_sequence<alim>{}, a, P, Q);

  P.resize(res_len);
}
#define int long long
vector<int> operator *(vector<int> v3,vector<int> v4)
{
    vector<int32_t> v1(v3.size()),v2(v4.size());for(int i=0;i<v1.size();++i) v1[i]=v3[i]; for(int i=0;i<v2.size();++i) v2[i]=v4[i];
    v1.reserve(v1.size()+v2.size());v2.reserve(v1.size()+v2.size());
  fast_polymult(v1,v2);
  vector<int> res(v1.size());
  for(int i=0;i<v1.size();++i) res[i]=v1[i];
  return res;
}
const int p=998244353;
int po(int a,int b) {if(b==0) return 1; if(b==1) return a; if(b%2==0) {int u=po(a,b/2);return (u*1LL*u)%p;} else {int u=po(a,b-1);return (a*1LL*u)%p;}}
int inv(int x) {return po(x,p-2);}
const int B=2005;
const int maxn=2*B;
int f[B][B];
int fact[maxn];int invf[maxn];
vector<int> rev(vector<int> A)
{
    int n=A.size();
    vector<int> v1(n),v2(n+1);
    for(int i=0;i<n;++i) {v1[i]=(A[i]*fact[i])%p;}
    for(int diff=0;diff<n;++diff) {v2[n-diff]=(diff%2==0 ? invf[diff] : (p-invf[diff])%p);}
    vector<int> v3=v1*v2;
    vector<int> B(n);
    for(int i=0;i<n;++i)
    {
        B[i]=(v3[n+i]*invf[i])%p;
    }
    return B;
}
vector<int> rev2(vector<int> A)
{
    int n=A.size();
    vector<int> v1(n),v2(n+1);
    for(int i=0;i<n;++i) {v1[i]=(A[i]*fact[i])%p;}
    for(int diff=0;diff<n;++diff) {v2[n-diff]=(invf[diff]);}
    vector<int> v3=v1*v2;
    vector<int> B(n);
    for(int i=0;i<n;++i)
    {
        B[i]=(v3[n+i]*invf[i])%p;
    }
    return B;
}
int h[maxn][maxn];int Q[maxn][maxn];
int res[maxn][maxn];
int C[maxn][maxn];
int32_t main()
{
    ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    for(int i=0;i<maxn;++i)
    {
        for(int j=0;j<=i;++j)
        {
            if(j==0 || j==i) {C[i][j]=1;continue;}
            C[i][j]=C[i-1][j]+C[i-1][j-1];if(C[i][j]>=p) C[i][j]-=p;
        }
    }
    fact[0]=1; for(int i=1;i<maxn;++i) {fact[i]=(fact[i-1]*i)%p;} for(int i=0;i<maxn;++i) {invf[i]=inv(fact[i]);}
    f[0][0]=1;
    for(int d=B-1;d>=1;--d)
    {
        for(int nx=B-1;nx>=0;--nx)
        {
            for(int nz=(B-1)/d;nz>=0;--nz)
            {
                if(nx+d+1<B && nz+1<B)
                {
                    f[nx+d+1][nz+1]-=f[nx][nz];if(f[nx+d+1][nz+1]<0) f[nx+d+1][nz+1]+=p;
                }
            }
        }
        vector<int> AA,BB;
        for(int nx=0;nx<B-d;++nx)
        {
            AA.clear();BB.clear();
            int deg=(B-1)/d;
            for(int i=0;i<deg;++i)
            {
                AA.app(f[nx][i]);
            }
            while(!AA.empty() && AA.back()==0) {AA.pop_back();}
            if(AA.empty()) continue;
            BB=rev(AA);
            for(int i=0;i<BB.size();++i)
            {
                if(i+d<B && nx+d<B)
                {
                    h[nx+d][i+d]+=BB[i];if(h[nx+d][i+d]>=p) h[nx+d][i+d]-=p;
                }
                if(i+d-1<B && nx+d<B)
                {
                    h[nx+d][i+d-1]-=BB[i];if(h[nx+d][i+d-1]<0) h[nx+d][i+d-1]+=p;
                }
            }
        }
    }
    vector<int> AA,BB;
    for(int nx=0;nx<B;++nx)
    {
        AA.clear();BB.clear();
        int deg=B;
        for(int i=0;i<deg;++i)
        {
            AA.app(h[nx][i]);
        }
        while(!AA.empty() && AA.back()==0) {AA.pop_back();}
        if(AA.empty()) continue;
        BB=rev2(AA);
        for(int i=0;i<BB.size();++i)
        {
            h[nx][i]=BB[i];
        }
    }
    Q[0][0]=1;
    for(int d=B-1;d>=1;--d)
    {
        for(int nx=0;nx<B-d;++nx)
        {
            for(int nz=(B-1)/d;nz>=0;--nz)
            {
                if(nx+d<B && nz+1<B)
                {
                    Q[nx+d][nz+1]+=Q[nx][nz];if(Q[nx+d][nz+1]>=p) Q[nx+d][nz+1]-=p;
                }
            }
        }
    }
    vector<int> h1(2*B*B),Q1(2*B*B);
    for(int i=0;i<B;++i)
    {
        for(int j=0;j<B;++j)
        {
            h1[2*B*i+j]=h[i][j];
            Q1[2*B*i+j]=Q[i][j];
        }
    }
    //vector<int> h2(B*B),h3(B*B),Q2(B*B),Q3(B*B);
    //for(int i=0;i<B*B;++i) {h2[i]=h1[i];h3[i]=h1[i+B*B];Q2[i]=Q1[i];Q3[i]=Q1[i+B*B];}
    vector<int> res1=h1*Q1;
    for(int i=0;i<B;++i)
    {
        for(int j=0;j<B;++j)
        {
            int el=2*i*B+j;
            res[i][j]=res1[el];
        }
    }
    int t;cin>>t;
    while(t--)
    {
        int n,m;cin>>n>>m;
        int answ=0;
        for(int d=1;d<=n;++d)
        {
            answ+=res[m][d]*C[n-1][d-1];answ%=p;
        }
        cout<<answ<<'\n';
    }
    return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 2940ms
memory: 716224kb

input:

3
1 3
2 3
3 3

output:

1
4
10

result:

ok 3 number(s): "1 4 10"

Test #2:

score: 0
Accepted
time: 2901ms
memory: 727380kb

input:

1
2000 2000

output:

204576309

result:

ok 1 number(s): "204576309"

Test #3:

score: 0
Accepted
time: 2982ms
memory: 728648kb

input:

100000
10 1752
19 171
17 1105
14 687
28 204
3 1215
19 1610
30 764
6 537
42 656
41 943
36 795
28 795
9 740
28 1138
20 173
6 1160
21 1409
18 851
28 301
30 782
4 685
10 1792
15 868
42 1341
10 1361
4 1278
28 61
30 1943
44 1199
23 1398
25 1199
34 951
14 866
4 1469
4 1060
30 567
22 1805
50 1566
39 537
25 ...

output:

268773463
258398110
748990072
944261206
28848324
1415323
440426423
133920075
975812871
422247730
443385987
269602349
516611815
864790546
323341799
910043327
459119274
782783928
662557529
928314001
831289605
119493832
694722015
789549109
307680352
415179306
774755603
202375583
226239893
400583167
282...

result:

ok 100000 numbers

Test #4:

score: -100
Time Limit Exceeded

input:

100000
98 437
75 1936
82 522
51 1166
67 1452
96 618
96 1436
91 1173
100 1242
69 1280
74 125
73 869
77 811
73 1694
56 1550
65 1857
75 941
79 538
68 1057
71 907
90 1925
86 785
65 1658
60 1044
67 804
56 1428
53 127
97 197
57 680
81 1636
64 1200
79 790
92 1389
91 340
78 411
58 1308
70 952
90 85
91 1397
...

output:

742593766
791182960
260925178
423870975
954765117
233028625
298697835
166927245
254797666
165773109
608132753
508968899
726675390
951161570
757337043
102586936
115466851
787049646
41560035
882840713
26484816
898027489
538836045
445749214
446547003
117114483
182473853
404451392
352694143
378208316
32...

result: