結果
| 問題 |
No.886 Direct
|
| コンテスト | |
| ユーザー |
hasegawa1
|
| 提出日時 | 2021-08-24 00:30:19 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
RE
|
| 実行時間 | - |
| コード長 | 5,175 bytes |
| コンパイル時間 | 1,413 ms |
| コンパイル使用メモリ | 87,596 KB |
| 最終ジャッジ日時 | 2025-01-24 01:43:28 |
|
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | RE * 4 |
| other | RE * 32 |
ソースコード
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <cstdint>
#include <cassert>
#include "atcoder/modint"
using namespace std;
using mint = atcoder::modint1000000007;
class Sieve {
private:
const int _n;
std::vector<int> _max_prime_factor;
std::vector<int> _euler_phi;
public:
explicit Sieve(int n = 2'000'000): _n(n+1), _max_prime_factor(_n), _euler_phi(_n) {
iota(_euler_phi.begin(), _euler_phi.end(), 0);
for(int i=2; i<_n; i++) {
if(_max_prime_factor[i]) continue;
for(int j=i; j<_n; j+=i) {
_max_prime_factor[j] = i;
_euler_phi[j] -= _euler_phi[j]/i;
}
}
}
bool is_prime(int64_t n) const {
assert(n > 0);
if(n < _n) return (_max_prime_factor[n] == n);
return atcoder::internal::is_prime_constexpr(n);
}
std::vector<std::pair<int64_t,int64_t>> prime_factorize(int64_t n) const {
assert(n > 0);
std::vector<std::pair<int64_t,int64_t>> res;
if(n < _n) {
while(n > 1) {
int64_t p = _max_prime_factor[n];
int64_t exp = 0;
while(_max_prime_factor[n] == p) {
n /= p;
++exp;
}
res.emplace_back(p, exp);
}
std::reverse(res.begin(), res.end());
} else {
for(int64_t i=2; i*i<=n; i++) {
if(n%i == 0) {
int exp = 0;
while(n%i == 0) {
n /= i;
++exp;
}
res.emplace_back(i, exp);
}
}
if(n != 1) res.emplace_back(n, 1);
}
return res;
}
std::vector<int64_t> divisors(int64_t n) const {
assert(n > 0);
std::vector<int64_t> res = {1};
for(const auto [p, exp]: prime_factorize(n)) {
int sz = res.size();
for(int i=0; i<sz; i++) {
int64_t now = res[i];
for(int j=0; j<exp; j++) {
now *= p;
res.emplace_back(now);
}
}
}
sort(res.begin(), res.end());
return res;
}
int64_t euler_phi(int64_t n) const {
assert(n > 0);
if(n < _n) return _euler_phi[n];
int64_t res = n;
for(const auto [p, exp]: prime_factorize(n)) {
res -= res/p;
}
return res;
}
template<typename T>
std::vector<T> divisor_transform(std::vector<T> v) {
assert(v.size() <= _n);
for(int i=2; i<_n; i++) {
if(is_prime(i)) {
for(int j=1; i*j<_n; j++) {
v[j * i] += v[j];
}
}
}
return v;
}
template<typename T>
std::vector<T> inverse_divisor_transform(std::vector<T> v) {
assert(v.size() <= _n);
for(int i=2; i<_n; i++) {
if(is_prime(i)) {
for(int j=(_n-1)/i; i>0; j--) {
v[j * i] -= v[j];
}
}
}
return v;
}
template<typename T>
std::vector<T> multiple_transform(std::vector<T> v) {
assert(v.size() <= _n);
for(int i=2; i<_n; i++) {
if(is_prime(i)) {
for(int j=(_n-1)/i; i>0; j--) {
v[j] += v[j * i];
}
}
}
return v;
}
template<typename T>
std::vector<T> inverse_multiple_transform(std::vector<T> v) {
assert(v.size() <= _n);
for(int i=2; i<_n; i++) {
if(is_prime(i)) {
for(int j=1; i*j<_n; j++) {
v[j] -= v[j * i];
}
}
}
return v;
}
template<typename T>
std::vector<T> gcd_convolution(const std::vector<T> &a, const std::vector<T> &b) {
assert(a.size() == b.size());
auto sum_a = multiple_transform(a);
auto sum_b = multiple_transform(b);
std::vector<T> sum_c;
std::transform(sum_a.begin(), sum_a.end(), sum_b.begin(), std::back_inserter(sum_c), std::multiplies<T>());
return inverse_multiple_transform(sum_c);
}
template<typename T>
std::vector<T> lcm_convolution(const std::vector<T> &a, const std::vector<T> &b) {
assert(a.size() == b.size());
auto sum_a = divisor_transform(a);
auto sum_b = divisor_transform(b);
std::vector<T> sum_c;
std::transform(sum_a.begin(), sum_a.end(), sum_b.begin(), std::back_inserter(sum_c), std::multiplies<T>());
return inverse_divisor_transform(sum_c);
}
};
int main(void) {
cin.tie(nullptr);
ios_base::sync_with_stdio(false);
Sieve s;
int H, W;
cin >> H >> W;
int M = max(H, W);
vector<mint> h(M+1), w(M+1);
for(int i=1; i<H; i++) {
h[i] = H-i;
}
for(int i=1; i<W; i++) {
w[i] = W-i;
}
mint ans = (H-1)*W + H*(W-1) + s.gcd_convolution(h, w)[1];
cout << ans.val() << endl;
}
hasegawa1