u_sho競プロぶろぐ

21歳。みゃーくぴとぅ。ゆる~く続けますたぶん。  デザイン変えました(2019/2/25)これでいきます

yukicoder April Fool Contest 2021 No.3077, No.3085

いやー難しかったです(好き

全部は解いていませんし、解いた問題を全て(6つしかないですが)解説すると大変なので2つだけ

E: No.3077 🔧

まず項目があるのに問題文、制約、サンプル等が読めないことに着目します。
きっと読めない状態になっているということです。
ブラウザの開発者ツールを開いてみます。

a×b+c-d を k で割った余りを出力してください。
No.3077 🔧 を開発者ツールでみた画像

ビンゴです! なんと問題文が HTML の class 属性名になっていました。

つまり、

  • 問題
    • a×b+c-d を k で割った余りを出力してください。
  • 制約
    • 1 <= a, b, c, d, k <= 10^9
    • ab + c >= d
    • 入力はすべて整数。
  • 入力
    • $a\ b\ c\ d\ k$
  • 出力
    • a×b+c-d を k で割った余りを出力してください。最後に改行してください。

ということですね。
制約より、a*b および (a%k)*(b%k) は 32 bit 整数に収まらないですが、
ab + c - d は 64 bit 整数には収まるので、次のように解けます。

#include<iostream>
int main(){
  long long a,b,c,d,k;
  std::cin>>a>>b>>c>>d>>k;
  std::cout<<(a*b+c-d)%k<<"\n";
}

問題文さえ読めれば ABC A問題程度の難易度でしたネ🎃

M: No.3085 Math...?

まず真面目に考えます。

u-sho「愚直?」
u-sho2「間に合わん」
u-sho「じゃあ総和部分の値を保存しておいて」
u-sho2「それでも間に合わないね」
u-sho「演算のいい性質がある?」
u-sho2「具体的に Do you know?」
u-sho「知りません。難しすぎませんか?」

時間切れです。ここで解説をみました。この問題は解けないらしいです。なるほどニャ(?

ところで、問題文の下の空行がやけに多いですね。何かあるんでしょうか?

例により開発者ツールを開いてみます

白文字の数式があるようです
No.3085 Math...? を開発者ツールでみた画像

ありましたね......

font タグ*1の color 属性で white にされているようなので、ここを black に編集して見えるようにしてみます。

数式モードで書かれたリンクが表示されました
No.3085 Math...? を開発者ツールで編集してみた画像

Googleドキュメントへのリンクが表示されましたね。
打ち込むのが大変でしょうからここに貼っておきます。
https://docs.google.com/document/d/14UQE9wc6K-YRyN56WYiF6Z7WQ1AkT8qVg17VdWrjeTg/edit?usp=sharing
docs.google.com

しかし、ここにもおかしなことが書いてあります。

1+2+3+4+...+100=5050です。5050を1000000007で割った余りの1を出力してください。

5050 を 1000000007 で割った余りは当然 5050 ですから、これはおかしいですね。
そういえば、サンプルの下の空行がやけに多いですね。何かあるんでしょうか。

3053 306e から始まる英数文字列がファイル末尾に現れました
No.3085 の Googleドキュメントを全選択してみた画像

ありましたね......

16進数でしょうか。文字列か、最大4桁ということは 64bit 整数かもしれませんね。
とりあえず以下のようなコードを書いて変換してみます。

#include<stdio.h>
int main(){
  long long c;
  while(~scanf("%x", &c)) printf("%c", c);
}

ascii 範囲外の文字は化けましたが、とりあえず次のような出力になりました

Sn�(https://yukicoder.me/problems/6059)n�OL�e�6go�K�fD�0ojD�nhWf�gO`UD~_�3o6U�n_�ƹȱ�k+~�~[�

明らかに文字列です。つまりこれを UTF16 なりなんなり*2で見てあげればいいわけですね。

C や C++ でこれをやるのは大変な気がしたので、JavaScript を使います。

まず、JavaScriptUnicode リテラル(参考:
文字クラス - JavaScript | MDN
)に変換します。
適当なエディタに先程の文字列をコピペし、[0-9a-f]+ や !\s を \u{$1} のような形に置換すると良いです。
結果はこんな感じ(文字列は適当な長さで分割しています)

const str = "\u{3053}\u{306e}\u{30da}\u{30fc}\u{30b8}"
            + "\u{28}\u{68}\u{74}\u{74}\u{70}\u{73}\u{3a}\u{2f}\u{2f}"
            + "\u{79}\u{75}\u{6b}\u{69}\u{63}\u{6f}\u{64}\u{65}"
            + "\u{72}\u{2e}\u{6d}\u{65}\u{2f}\u{70}\u{72}\u{6f}"
            + "\u{62}\u{6c}\u{65}\u{6d}\u{73}\u{2f}\u{36}\u{30}"
            + "\u{35}\u{39}\u{29}\u{306e}\u{5185}\u{3001}"
            + "\u{554f}\u{984c}\u{6587}\u{3001}\u{5165}"
            + "\u{529b}\u{3001}\u{5236}\u{7d04}\u{3067}"
            + "\u{306f}\u{3001}\u{66f8}\u{304b}\u{308c}"
            + "\u{3066}\u{3044}\u{308b}\u{30}\u{306f}\u{306a}"
            + "\u{3044}\u{3082}\u{306e}\u{3068}\u{3057}"
            + "\u{3066}\u{8aad}\u{3093}\u{3067}\u{304f}"
            + "\u{3060}\u{3055}\u{3044}\u{3002}\u{307e}"
            + "\u{305f}\u{3001}\u{30b5}\u{30f3}\u{30d7}\u{30eb}"
            + "\u{33}\u{306f}\u{5236}\u{7d04}\u{9055}\u{53cd}"
            + "\u{306e}\u{305f}\u{3081}\u{30c6}\u{30b9}\u{30c8}"
            + "\u{30b1}\u{30fc}\u{30b9}\u{306b}\u{542b}"
            + "\u{307e}\u{308c}\u{307e}\u{305b}\u{3093}\u{3002}"

そしてこれを console.log してあげれば良いわけです。

f:id:u_sho:20210402163155p:plain
No.3085 の 本質部分を表示させた画像

はい、出てきましたね。

このページ(https://yukicoder.me/problems/6059)の内、問題文、入力、制約では、書かれている0はないものとして読んでください。また、サンプル3は制約違反のためテストケースに含まれません。

なるほどです(元の問題文なんだったっけ←)

つまり元の問題文

正整数 A,\ B が与えられるので、\prod_{i=1}^A \sum_{j=1}^B j^i1000000007 で割った余りを出力してください。この問題は Q ケース与えられます。

入力、制約

  • 入力は全て整数
  • 1\leq Q \leq 10^5
  • 1\leq A_i \leq 10^9
  • 1\leq B_i \leq 20210401

は次のようになるということですね。

  • 問題
    • 正整数 A(=1),\ B が与えられるので、\prod_{i=1}^A \sum_{j=1}^B j^i(制約より、\sum_{j=1}^B j)を 17 で割った余りを出力してください。この問題は Q(=1) ケース与えられます。
  • 制約
    • 入力は全て整数
    • 1\leq Q \leq 1^5 つまり Q=1
    • 1\leq A_i \leq 1^9 つまり A=1
    • 1\leq B_i \leq 22141

ゆえに

#include<iostream>
int main(){
  int Q, A, B;
  std::cin >> Q >> A >> B;
  long long sum = 0;
  for (int i=1; i<B; i++) sum += i;
  std::cout << sum << "\n";
}

となります。

ゴルフ

ところで、\sum_{j=1}^B j = \frac{B}{2}(B+1) であることが知られています(参考:等差数列の和の公式の例題と証明など | 高校数学の美しい物語
なので、C(gcc) でコードゴルフをすると次のようにも書けます。

B;main(){scanf("%d%d%d",&B,&B,&B);printf("%d",B++*B/2%17);}

2021/4/2 17:06 時点で Bash に次いで2番目です(お行儀の悪い提出をしています。ごめんなさい)
ruby とかも結構短く書けるはずなので皆さんもお試しあれ

以上

ばいちゃ!

*1:HTML5 では廃止されています。使わないようにしましょう

*2:最大4桁あるので UTF8 には収まっていなそう