LoginSignup
0
0

More than 3 years have passed since last update.

Perl で学ぶ逆元の3 ABC 151 E が解けた!

Last updated at Posted at 2020-03-17

はじめに

逆元問題が好きになってきたので、調子に乗って E - Max-Min Sums に挑戦したが、難易度水色だったため簡単に解けるはずもなく気持ちが Light Blue になりながらも、何とか乗り切った話。

E - Max-Min Sums

AtCoder Beginner Contest 151 E - Max-Min Sums
答えは非常に大きくなる可能性があるので、

mod\ 10^9 +7

で出力してください。
この時点で、テンションは Max だった。

嵌ったところ

before1.pl
  $ans += $a[$n-$i-1] * $c;
  $ans %= $MOD;
  $ans += ($MOD - $a[$i]) * $c;
  $ans %= $MOD;

足し算なのでそのまま加えていましたが、加える変数 \$a が負の場合、WA となるケースが考えられます。

after1.pl
  $ans += ($MOD + $a[$n-$i-1]) * $c; # 負にならない様、法を加算
  $ans %= $MOD;
  $ans += ($MOD - $a[$i]) * $c;
  $ans %= $MOD;
before2.pl
use Math::BigInt; # perl の bigint は圧倒的に遅い

my $modinv = sub {
  my $a = shift;
  Math::BigInt->new($a)->bmodinv($MOD); # BigInt メソッド
};

この投稿 で、Math::BigInt の味を占めたので使用しましたが、perl の bigint は圧倒的に遅い に気付かず TLE の山。

after2.pl
my $modinv = sub {
  my $a = shift;
  $modpow->($a, $MOD - 2); # 自作関数
};

解けたところ

ABC151E.pl
use v5.18; # strict say state
use warnings;

my ($n, $k) = split / /, <STDIN>;
my @a = split / /, <STDIN>;
@a = sort { $a <=> $b } @a;
my $MOD = 1e9 + 7;
my $modpow = sub {
  my ($a, $n) = @_;
  my $r = 1;
  while ($n > 0) {
    $r = $r * $a % $ MOD if $n & 1;
    $a = $a * $a % $MOD;
    $n >>= 1;
  }
  return $r;
};
my $modinv = sub {
  my $a = shift;
  $modpow->($a, $MOD - 2);
};
my (@fac, @finv);
$fac[0] = 1;
$finv[0] = 1;
for my $i (1..$n) {
  $fac[$i] = $fac[$i-1] * $i % $MOD;
  $finv[$i] = $modinv->($fac[$i]);
}
my $combi = sub {
  my ($n, $k) = @_;
  $fac[$n] * ($finv[$n-$k] * $finv[$k] % $MOD) % $MOD;
};
my $ans = 0;
for (my $i=0; $i<=$n-$k; $i++) {
  my $c = $combi->($n-$i-1, $k-1);
  $ans += ($MOD + $a[$n-$i-1]) * $c;
  $ans %= $MOD;
  $ans += ($MOD - $a[$i]) * $c;
  $ans %= $MOD;
}
say $ans;
AC

どやっ

まとめ

  • 水色は骨のあるやつだった

参照したサイト

追記

BigInt を使用すると100倍遅いことが分かりました
Perl AtCoderでベンチマーク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0