関連トピック:
タイトル説明
長さ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);
}
}
最後に、ご指導ありがとうございます