【刀指募集】_13円の最後の数字

タイトルの説明

6月1日の子供の日には、Niu Keが孤児院の子供たちを訪問するためのいくつかのささやかな贈り物を準備しますが、これは今年もそうです。Niu Keの上級ベテランとして、HFは自然にいくつかの小さなゲームを準備しました。その中には、次のようなゲームがあります。まず、子供たちに大きな輪を作らせます。それから、彼は番号mをランダムに割り当て、番号0の子供が報告し始めました。m-1と叫ぶ子供が歌を歌いたいときはいつでも、ギフトボックスでギフトを選ぶことができます。次の子供から始めて、サークルに戻らなくなり、0…m-1を続けます。番号を報告してください...このように続けてください...最後の子供が去るまで、あなたは実行する必要がなくなり、名誉ある「名探偵コナン」のNiu Keコレクターズエディションを入手できます(限られた場所!! _このギフトを贈るのはどの子供ですか?(注:子供の数は0からn-1までです)
子供のいない場合は、-1を返します

問題解決のアイデア

入力シーケンスの要素を削除した後、シーケンスの長さが変わることに気づきました。
削除された要素の位置でインデックス(配列の添え字)が計算され始めると、削除された各要素について、シーケンスの長さが1つずつ減少し、インデックスは完全になります。変化。変更前のインデックスと新しいインデックスの対応
を見つけることができれば、問題は簡単に解決できます。

関数f(n、m)を定義します。これは、n個の数値0,1,2,3、...、n-1のそれぞれのm番目の数値を削除した後に残った数値を意味し
ます。次に、最初に削除された番号のインデックスは(m-1)%n(たとえば、合計で10人の子供がいて、5番目はウォーキングであり、配列内のウォーキングしている子供の添え字は(5-1)%10 = 4)です。
インデックス要素を削除すると、残りのn-1個の数値
はになり0,1,2,…,k-1,k+1,…,n-1ます。次に番号を削除するときは、k + 1の位置からなので、シーケンスを考えることができますk+1,..,n-1,0,1,…,k-1シーケンスの最後のシーケンスもfの関数です。ただし、この関数は最初の関数とは異なり、f 'で表されるマッピング関係があるため、f(n、m)= f'(n-1、m)となります。次に、マッピング関係を見つける必要があります。

0からn-1までの番号が付けられたシーケンスを指定します。そのうち、kはシリアル番号の次の番号、つまりk-1デキューを表します。

a 0、1、…、k-1、k、k + 1、…、n-1

次に、シーケンス番号は(m-1)%n、k = m%nです(これは本当に明白です)。k-1をデキューした後、シーケンスは次のようになります。

b 0、1、…、k-2、k、k + 1、…、n-1

次に、このシーケンスをn-1の後に拡張し続けます。

c '0、1、…、k-2、k、k + 1、…、n-1、n、n + 1、…、n + k-2

kからn + k-2までのシーケンスを取ります。実際、このシーケンスはシーケンスbのシーケンス0〜k-2をシーケンスbの後ろに移動すると見なすことができます。このようにして、新しいシーケンスが取得されます

ck、k + 1、…、n-1、n、n + 1、…、n + k-2

さて、シーケンスc全体に対して1 kを引いて、get

d 0、1、…、n-2

cシーケンスのn-1、n、n + 1からk-1を引いたものは何ですか?これは心配する必要はありません。とにかく、cシーケンスは連続的であり、頭と尾がわかっているので、dシーケンスがどのように見えるかを知ることができます。
このように、シーケンスaからシーケンスdへの変換はシーケンスnからシーケンスn-1への変化であることがわかりますジョセフのリングは再帰を使用して最終結果を取得できます。はい、続けます。

残りは、n-1シーケンスに従ってnシーケンスに再帰的です。シーケンスdであるn-1シーケンスで、最後に残ったシーケンス番号が
プッシュバックするxであることがわかっているとします。

  1. d-> c、同時にkを減算しただけ、今回は同時にkを加算するとx + k。

  2. c-> b、(x + k)%n。%n後。k〜n-1のシーケンス値は変更されず、n〜n + k-2のシーケンスは0〜k-2になります。これら2つのシーケンスの組み合わせはシーケンスbです。

  3. x =(x + k)%n。そして、k = m%nなので、x =(x + m%n)%n = (x + m)%n ;

  4. f [i] =(f [i-1] + m)%i

コードの実装

class Solution {
public:
    int LastRemaining_Solution(int n, int m)
    {
        if(n==0)
            return -1;
        if(n==1)
            return 0;
        return (LastRemaining_Solution(n-1,m)+m)%n;
    }
};
253件の元の記事を公開しました 賞賛されました41 40,000回以上の閲覧

おすすめ

転載: blog.csdn.net/liuyuchen282828/article/details/103943953