QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#125525 | #6328. Many Products | Energy_is_not_over# | WA | 43ms | 44996kb | C++17 | 11.7kb | 2023-07-16 19:59:19 | 2023-07-16 19:59:23 |
Judging History
answer
//#pragma GCC optimize("Ofast", "unroll-loops")
//#pragma GCC target("sse", "sse2", "sse3", "ssse3", "sse4")
#ifdef __APPLE__
#include <iostream>
#include <cmath>
#include <algorithm>
#include <stdio.h>
#include <cstdint>
#include <cstring>
#include <string>
#include <cstdlib>
#include <vector>
#include <bitset>
#include <map>
#include <queue>
#include <ctime>
#include <stack>
#include <set>
#include <list>
#include <random>
#include <deque>
#include <functional>
#include <iomanip>
#include <sstream>
#include <fstream>
#include <complex>
#include <numeric>
#include <cassert>
#include <array>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <thread>
#else
#include <bits/stdc++.h>
#endif
#define all(a) a.begin(),a.end()
#define len(a) (int)(a.size())
#define mp make_pair
#define pb push_back
#define fir first
#define sec second
#define fi first
#define se second
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
typedef long double ld;
template<typename T>
bool umin(T &a, T b) {
if (b < a) {
a = b;
return true;
}
return false;
}
template<typename T>
bool umax(T &a, T b) {
if (a < b) {
a = b;
return true;
}
return false;
}
#if __APPLE__
#define D for (bool _FLAG = true; _FLAG; _FLAG = false)
#define LOG(...) print(#__VA_ARGS__" ::", __VA_ARGS__) << endl
template <class ...Ts> auto &print(Ts ...ts) { return ((cerr << ts << " "), ...); }
#else
#define D while (false)
#define LOG(...)
#endif
const int max_n = 2e5+10, inf = 1000111222;
ll __gcd(ll a,ll b)
{
while (a&&b){
if (a>=b){
a%=b;
}
else{
b%=a;
}
}
return a+b;
}
const int mod = 998244353;
const int md=mod;
/*
* long long version
long long mul(long long a, long long b) {
long long x = (long double) a * b / mod;
long long y = (a * b - x * mod) % mod;
return y < 0 ? y + mod : y;
}
long long power(long long a, long long b) {
if (b == 0) {
return 1 % mod;
}
if (b % 2 == 0) {
return power(mul(a, a), b / 2);
}
return mul(a, power(a, b - 1));
}*/
inline void inc(int &x, int y) {
x += y;
if (x >= mod) {
x -= mod;
}
}
inline void dec(int &x, int y) {
x -= y;
if (x < 0) {
x += mod;
}
}
inline int mul(int x, int y) {
return (1LL * x * y) % mod;
}
int power(int a, int b) {
int res = 1 % mod;
while (b) {
if (b % 2) {
res = mul(res, a);
}
b /= 2;
a = mul(a, a);
}
return res;
}
int inv(int x) {
return power(x, mod - 2);
}
string str_fraction(int x, int n = 20) {
stringstream res;
pair<int, int> best(x, 1);
for (int j = 1; j < n; ++j) {
best = min(best, {mul(x, j), j});
best = min(best, {mod - mul(x, j), -j});
}
if (best.second < 0) {
best.first *= -1;
best.second *= -1;
}
res << best.first << "/" << best.second;
return res.str();
}
const int max_f = 2e5+10;
int f[max_f], rf[max_f];
void get_all_f() {
f[0] = rf[0] = 1;
for (int i = 1; i < max_f; ++i) {
f[i] = mul(i, f[i - 1]);
}
rf[max_f - 1] = inv(f[max_f - 1]);
for (int i = max_f - 2; i > 0; --i) {
rf[i] = mul(i + 1, rf[i + 1]);
}
}
int get_c(int n, int k) {
if (n < k) {
return 0;
}
return mul(f[n], mul(rf[k], rf[n - k]));
}
class Factorizer {
public:
Factorizer(): generator(time(0)) {
memset(d, 0, sizeof(d));
for (int i = 2; i < max_p; ++i) {
if (!d[i]) {
d[i] = i;
for (long long j = 1LL * i * i; j < max_p; j += i) {
if (!d[j]) {
d[j] = i;
}
}
}
}
}
static long long mul(long long a, long long b, long long mod) {
long long x = (long double) a * b / mod;
long long y = (a * b - x * mod) % mod;
return y < 0 ? y + mod : y;
}
static long long power(long long a, long long b, long long mod) {
long long res = 1 % mod;
while (b) {
if (b % 2) {
res = mul(res, a, mod);
}
b /= 2;
a = mul(a, a, mod);
}
return res;
}
/* works for x <= 3.8 * 10^18
* doesn't work 3825123056546413051
*/
static bool is_prime(long long x) {
for (int val : {2, 3, 5, 7, 11, 13, 17, 19, 23}) {
if (x == val) {
return true;
}
if (!miller_simple(x, val)) {
return false;
}
}
return true;
}
vector<long long> factorize(long long x) {
vector<long long> res;
factorize(x, res);
sort(res.begin(), res.end());
return res;
}
vector<pair<long long, int>> factorize_count(long long x) {
vector<long long> res = factorize(x);
vector<pair<long long, int>> v;
for (int i = 0; i < res.size(); ) {
int pos = i;
while (i < res.size() && res[pos] == res[i]) {
++i;
}
v.push_back({res[pos], i - pos});
}
return v;
}
vector<long long> get_all_divisors(long long x, bool need_sort = false) {
auto v = factorize_count(x);
vector<long long> res;
generate_all_divisors(0, 1, v, res);
if (need_sort) {
sort(res.begin(), res.end());
}
return res;
}
private:
static const int max_p = 1000000;
int d[max_p];
mt19937_64 generator;
vector<long long> p;
static bool miller_simple(long long a, long long b) {
long long c = a - 1;
int k = __builtin_ctzll(c);
c >>= k;
b = power(b, c, a);
if (b == 1) {
return true;
}
for (int i = 0; i < k; ++i) {
if (b + 1 == a) {
return true;
}
b = mul(b, b, a);
}
return false;
}
long long polard_rho(long long a) {
const int max_v = 25;
while (true) {
long long p0 = generator() % a;
long long p1 = p0;
long long c = generator() % a;
long long ans = 1;
int t = 0;
int pos = 0;
vector<long long> arr{p1};
while (true) {
for (int i = 0; i < 2; ++i) {
p1 = mul(p1, p1, a) + c;
if (p1 >= a) {
p1 -= a;
}
arr.push_back(p1);
}
p0 = arr[pos++];
if (p0 == p1) {
break;
}
ans = mul(ans, llabs(p1 - p0), a);
if (ans == 0) {
return __gcd(llabs(p1 - p0), a);
}
if ((++t) == max_v) {
t = 0;
ans = __gcd(ans, a);
if (ans > 1 && ans < a) {
return ans;
}
}
}
ans = __gcd(ans, a);
if (ans > 1 && ans < a) {
return ans;
}
}
}
void factorize(long long a, vector<long long> &res) {
while (a > 1 && a < max_p) {
res.push_back(d[a]);
a /= d[a];
}
for (long long x : p) {
if (a % x == 0) {
a /= x;
res.push_back(x);
}
}
if (a < 2) {
return;
}
if (is_prime(a)) {
p.push_back(a);
res.push_back(a);
} else {
long long d = polard_rho(a);
assert(d > 1 && d < a);
factorize(d, res);
factorize(a / d, res);
}
}
void generate_all_divisors(int pos, long long x, const vector<pair<long long, int>> &v, vector<long long> &res) {
if (pos == v.size()) {
res.push_back(x);
return;
}
for (int i = 0; i <= v[pos].second; ++i) {
generate_all_divisors(pos + 1, x, v, res);
x *= v[pos].first;
}
}
};
Factorizer F;
int a[max_n];
const int max_d=6720;
vector<int> reb[max_d];
const int max_log = 42;
int dp[max_d][max_log];
int dp2[max_d][max_log];
int choose_a[max_n][max_log];
bool mark[max_n];
const bool debug=0;
mt19937 gen(47);
int main() {
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
ios_base::sync_with_stdio(0);
cin.tie(0);
get_all_f();
int n;
ll m;
if (debug){
n=2e5;
m=963761198400ll;
}
else{
cin>>n>>m;
}
for (int i=0;i<n;i++){
if (debug){
a[i]=gen()%mod;
}
else{
cin>>a[i];
}
inc(a[i],1);
}
vector<ll> divs = F.get_all_divisors(m,true);
for (int i=0;i<len(divs);i++){
for (int j=i+1;j<len(divs);j++){
if (divs[j]%divs[i]==0){
reb[i].pb(j);
mark[j]=1;
}
}
}
dp[0][0]=1;
for (int i=0;i<len(divs);i++){
for (int j=0;j<max_log;j++){
if (dp[i][j]==0){
continue;
}
for (auto to:reb[i]){
ll x=divs[to]/divs[i];
inc(dp[to][j+1],1ll*dp[i][j]*(x-1)%md);
}
}
}
dp2[0][0]=1;
for (int i=0;i<len(divs);i++){
for (int j=0;j<max_log;j++){
if (dp2[i][j]==0){
continue;
}
// LOG("dp2",divs[i],j,dp2[i][j]);
for (auto to:reb[i]){
inc(dp2[to][j+1],dp2[i][j]);
}
}
}
// for (int i=0;i<len(divs);i++){
// for (int j=1;j<max_log;j++){
// inc(dp2[i][j],dp2[i][j-1]);
// }
// }
choose_a[0][0]=1;
for (int i=0;i<n;i++){
for (int j=0;j<max_log;j++){
if (choose_a[i][j]==0){
continue;
}
inc(choose_a[i+1][j+1],choose_a[i][j]);
inc(choose_a[i+1][j],1ll*choose_a[i][j]*a[i]%md);
}
}
// vector<ll> primes;
// for (int i=1;i<len(divs);i++){
// if (!mark[i]){
// primes.pb(divs[i]);
// }
// }
int ans=0;
for (int i=0;i<len(divs);i++){
// int ways=0;
// vector<int> p_cnt;
// {
// ll X=m/divs[i];
// for (auto p:primes){
// if (X%p==0){
// p_cnt.pb(0);
// while (X%p==0){
// p_cnt.back()++;
// X/=p;
// }
// }
// }
// assert(X==1);
// }
// for (int k=0;k<min(max_log,n+1);k++){
//
// }
int rev_id=lower_bound(all(divs),m/divs[i])-divs.begin();
for (int j=0;j<max_log && j<=n;j++){
if (dp[i][j]==0){
continue;
}
for (int k=0;k<max_log && j+k<=n;k++){
int cur=1ll*choose_a[n][j]*dp[i][j]%md*dp2[rev_id][k]%md*get_c(n-j,k)%md;
// LOG(divs[i],j,cur,choose_a[n][j],dp[i][j],dp2[rev_id][k],get_c(n-j,k));
inc(ans,cur);
}
}
}
cout<<ans<<"\n";
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 9ms
memory: 13640kb
input:
2 3 0 1
output:
10
result:
ok 1 number(s): "10"
Test #2:
score: 0
Accepted
time: 9ms
memory: 13272kb
input:
5 1 0 1 2 3 4
output:
120
result:
ok 1 number(s): "120"
Test #3:
score: 0
Accepted
time: 9ms
memory: 13568kb
input:
10 314159265358 0 1 2 3 4 5 6 7 8 9
output:
658270849
result:
ok 1 number(s): "658270849"
Test #4:
score: -100
Wrong Answer
time: 43ms
memory: 44996kb
input:
200000 999999999989 823489320 406308599 710963770 183707427 192930969 941365774 318564299 391028855 945374838 651744270 515755727 220857626 599403217 214957584 335628890 771694833 40989299 34892948 630275822 869708185 432704750 924850167 707864789 232688853 406616372 529994171 782650336 979286144 65...
output:
227284539
result:
wrong answer 1st numbers differ - expected: '777405593', found: '227284539'