k回間隔Java

関連トピック

そして、Kのサブ配列

統計[美しいサブ配列]

タイトル説明
長さN、A1、A2、... ANのシーケンスが与えられ、連続するサブシーケンスAi、Ai + 1、... Ajの合計がKの倍数である場合、この間隔を[i、j]と呼びます。 K回のインターバルです。

シーケンス内のK分割区間の総数を見つけることができますか?

入力フォーマット

最初の行には、2つの整数NとKが含まれています。次のN
行のそれぞれに整数Aiが含まれています。

出力フォーマット

間隔のK倍の数を表す整数を出力します。

データ範囲

1≤N,K≤100000
1≤Ai≤100000

入力サンプル

5 2
1
2
3
4
5

出力例:

6

アイデア
1.質問を注意深く読むことは難しくありませんこれは1次元のプレフィックス合計問題です:与えられた配列LからRの合計がKの倍数である場合、答えはanscount ++です。
(接頭辞についてよくわからなくて、接頭辞について十分に説明しているブログを見つけた場合。ウェブサイトがDWVictorを公開しています。接頭辞と DWVictorが詳細に記述しました。権利を侵害している場合は、教えてください。ブログを書き始めたばかりです。いくつかのルールはあまり明確ではありません。何か問題がある場合は、批評して修正していただければ幸いです。)
この質問のデータは非常に大きく、タイムアウトする必要があります。プレフィックスの合計により、時間の複雑さが軽減されます。
2. LからRの合計はsum [R] -sum [L-1]で表されます。ドラフトペーパーにそれを描いてください。ここに画像の説明を挿入

3.上記の方法をガイドとして使用すると、次に行うことは非常に簡単です。いくつあるかを確認するだけsum[R]-sum[L-1]%K==0で、メソッドの二重ループを考えるのは簡単です。

  for(int i=1;i<=N;i++)
        for(int j=1;j<=i;j++){
    
    
           if((s[i]-s[j-1])%K==0&&s[i]-s[j-1]>0){
    
    
               
               count++;
           }

        }

ただし、この時間はまだ超過し、部分的なポイントしか取得できません。これはN<=100000、最悪の場合のダブルループを1の10乗で実行する必要があるため、1億を超えるため、最適化する必要があるためです。
4.ダブルループのタイムアウト、私たちはループを最適化し、ループを検討する必要があるため、一つの判定条件で開始する必要があります最適化するために、(sum[R]-sum[L-1])%K==0それは、二重ループの中で最も重要なコードは、私たちが式を変換することができます
(sum[R]-sum[L-1])%K==0- > sum[R]%K==sum[L-1]%Kからこの式を得ることができます:接頭辞の合計の係数をとった後、結果は等しくなります。2つの接頭辞の合計はk倍の間隔を形成できます。つまり、特定のKに対して、2つの接頭辞と%Kがある場合、結果は等しいです。このとき、LおよびRは、間隔k回を形成することができる。
5.私たちは、カウント、フェッチ[I]の結果を格納するカウント配列を使用表すiの間隔の数フェッチ値を我们要找的就是另一个值为私は的前缀和別のanscountが存在する場合、++ ;このようにして、doubleを単一の1-Nに変換できます。各接頭辞とsum[i]フェッチの結果は同じですanscount ++;
6. ループsum[0]%kが0になる前に別のポイントがあるため、残りが0の接頭辞は1つあるため、count [0] = 1;
次にすべてのコード


import java.util.Scanner;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner input=new Scanner(System.in);
        int N=input.nextInt();
        int K=input.nextInt();
        int count[]=new int [1000001];
        int arr[]=new int[N+1];
        int s[]=new int[N+1];
        for(int i=1;i<=N;i++){
    
    
            arr[i]=input.nextInt();
            s[i]=s[i-1]+arr[i];    //计算前缀和
            s[i]%=K;      //在这里直接对前缀和取摸
        }
        count[0]=1;
        long anscount=0;  //int 会爆掉

        for(int i=1;i<=N;i++)
        {
    
    
           anscount+=count[s[i]];//除了count[0]=1,其余的初始值都为0,                 
            count[s[i]]++;       //如果出现过一次后加1,出现过两次及以上,anscount++,      
            					 //我们就是要找总共有多少对,
            					 //只出现一次虽然count[i]加1但总的答案不会加
           }
        System.out.println(anscount);
    }
}

最後に、ご指導ありがとうございます

おすすめ

転載: blog.csdn.net/qq_44844588/article/details/106915847