結果
| 問題 |
No.890 移調の限られた旋法
|
| コンテスト | |
| ユーザー |
MarcusAureliusAntoninus
|
| 提出日時 | 2019-09-20 22:47:00 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 73 ms / 2,000 ms |
| コード長 | 3,770 bytes |
| コンパイル時間 | 2,267 ms |
| コンパイル使用メモリ | 197,164 KB |
| 最終ジャッジ日時 | 2025-01-07 18:48:37 |
|
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 32 |
コンパイルメッセージ
main.cpp: In function ‘int main()’:
main.cpp:168:19: warning: format ‘%lld’ expects argument of type ‘long long int*’, but argument 2 has type ‘int64_t*’ {aka ‘long int*’} [-Wformat=]
168 | scanf("%lld%lld", &N, &K);
| ~~~^ ~~
| | |
| | int64_t* {aka long int*}
| long long int*
| %ld
main.cpp:168:23: warning: format ‘%lld’ expects argument of type ‘long long int*’, but argument 3 has type ‘int64_t*’ {aka ‘long int*’} [-Wformat=]
168 | scanf("%lld%lld", &N, &K);
| ~~~^ ~~
| | |
| | int64_t* {aka long int*}
| long long int*
| %ld
main.cpp:168:14: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
168 | scanf("%lld%lld", &N, &K);
| ~~~~~^~~~~~~~~~~~~~~~~~~~
ソースコード
#include <bits/stdc++.h>
////////////
// ModInt //
////////////
// 四則演算の最も左に存在する値がModIntでなければキャストでバグる
// 例えばx = mint * 1000;やx = ModInt(1000) * mint;はいいがx = 1000 * mint;は駄目。
template<int64_t mod_ = 1'000'000'007>
class ModInt {
private:
int64_t integer_;
public:
constexpr ModInt(const int64_t initial_number = 0)
: integer_(initial_number){}
// 四則演算
constexpr ModInt operator+(const ModInt& operand) const
{
ModInt ret{this->integer_ + operand.integer_};
if (ret.integer_ >= mod_)
ret.integer_ -= mod_;
return ret;
}
constexpr ModInt operator-(const ModInt& operand) const
{
ModInt ret{this->integer_ - operand.integer_};
if (ret.integer_ < 0)
ret.integer_ += mod_;
return ret;
}
constexpr ModInt operator*(const ModInt& operand) const
{
return {this->integer_ * operand.integer_ % mod_};
}
constexpr ModInt operator/(const ModInt& operand) const
{
return *this * (operand ^ (mod_ - 2));
}
// 単項演算子
constexpr ModInt& operator++()
{
if (integer_ + 1 == mod_) integer_ = 0;
else integer_++;
return *this;
}
constexpr ModInt& operator--()
{
if (integer_ == 0) integer_ = mod_ - 1;
else integer_--;
return *this;
}
constexpr ModInt operator+()
{
return *this;
}
constexpr ModInt operator-()
{
if (integer_ == 0) return ModInt(0ll);
else return ModInt(mod_ - integer_);
}
// 累乗
constexpr ModInt operator^(const int64_t operand) const
{
ModInt ret{1}, pow_ope{this->integer_};
for (int64_t pow{operand}; pow > 0; pow >>= 1)
{
if (pow & 1) ret *= pow_ope;
pow_ope *= pow_ope;
}
return ret;
}
// 代入
constexpr ModInt& operator=(const ModInt& operand)
{
this->integer_ = operand.integer_;
return *this;
}
constexpr ModInt& operator+=(const ModInt& operand)
{
*this = *this + operand;
return *this;
}
constexpr ModInt& operator-=(const ModInt& operand)
{
*this = *this - operand;
return *this;
}
constexpr ModInt& operator*=(const ModInt& operand)
{
*this = *this * operand;
return *this;
}
constexpr ModInt& operator/=(const ModInt& operand)
{
*this = *this / operand;
return *this;
}
// その他
constexpr operator int64_t() { return integer_; }
constexpr ModInt getOne() const
{
return ModInt(1ll);
}
constexpr ModInt getZero() const
{
return ModInt(0ll);
}
};
using Mint = ModInt<>;
////////////////
// 組み合わせ //
///////////////
template<int64_t mod_ = 1'000'000'007, int max_ = 200'000>
class Combination {
public:
std::array<ModInt<mod_>, max_ + 1> inv, fact, finv;
Combination()
{
inv[0] = inv[1] = fact[0] = fact[1] = finv[0] = finv[1] = 1;
for (int num{2}; num <= max_; num++)
{
inv[num] = (mod_ - (int64_t)inv[mod_ % num] * (mod_ / num) % mod_) % mod_;
fact[num] = num * fact[num - 1] % mod_;
finv[num] = inv[num] * finv[num - 1] % mod_;
}
}
constexpr ModInt<mod_> getCombi(const int n, const int r) const
{
if (r < 0 || n < 0 || n - r < 0) return 0;
return fact[n] * finv[r] * finv[n - r];
}
constexpr ModInt<mod_> getPerm(const int n, const int r) const
{
if (r < 0 || n < 0 || n - r < 0) return 0;
return fact[n] * finv[n - r];
}
};
Combination<1'000'000'007, 1'000'000> combi;
int64_t calcGCD(int64_t a, int64_t b)
{
while (a)
{
b %= a;
std::swap(a, b);
}
return b;
}
int main()
{
int64_t N, K;
scanf("%lld%lld", &N, &K);
std::vector<Mint> table(N + 1);
for (int64_t i{N}; i > 1; i--)
{
if (N % i > 0 || K % i > 0) continue;
table[i] = combi.getCombi(N / i, K / i);
for (int64_t j{2 * i}; j <= N; j += i)
table[i] -= table[j];
}
Mint sum;
for (int i{2}; i <= N; i++)
sum += table[i];
std::cout << sum << std::endl;
return 0;
}
MarcusAureliusAntoninus