問題
難易度:人気-
説明:
https://www.luogu.com.cn/problem/P3131
配列を入力し、合計が7で割り切れる最長の部分文字列を見つけます。
入力範囲:
入力長:1≤N≤50,000
入力番号のサイズ:0…1,000,000
ケースを入力してください:
7
3
5
1
6
2
14
10
私のコード:
数学の質問を比較すると、それが直接暴力的である場合、n!時間計算量は、レベルごとにsum [i] = sum [i-1] + N、次に%7であっても、最長の時間計算量は次のようになります。 n ^ 2、それでも機能しない場合は、数学の問題になります。
2つの合計の解を考えると、7で割り切れる区間合計の長さを比較できます。
区間Mには、NとX、ΣM=ΣN+ΣX、および
ΣM%7 = 1、ΣN%7 = 1
ΣM%7-ΣN%7 = 0
(ΣM-ΣN)%7 = 0
ΣX%7 = 0 ——————>大きな区間Mから、区間Nが見つかった場合は、2を減算して、7で割り切れる区間Xを取得します。Nが可能な限り小さい場合は、 Xは7で割り切れる最長の区間であり、Xを取得するには、最初にNを取得します。つまり、Mの終了位置とNの開始位置を取得します。(ΣM%7 =ΣN%7、ここで両方の残りは7になります)
C ++の場合
#include <iostream>
using namespace std;
int num, temp, res = 0, be[8], en[8], sum[50001];
int main() {
cin >> num;
for (int i = num; i-- > 0;) { // 从尾到头获取逐个区间的和并求余(自动形成了所有同结尾的最大区间)
cin >> temp;
sum[i] = (temp + sum[i + 1]) % 7;
}
for (int i = num; i-- > 0;) // 然后得出相应的开始结束位置
if (en[sum[i]]) be[sum[i]] = i; else en[sum[i]] = i;
for (int i = 7; i-- > 0;) // 通过开始结束为止得出最大的区间
if(be[i] && en[i]) res = max(res, en[i] - be[i]);
cout << res;
}