Giriş massivini iki bərabər hissəyə bölün: t_1, t_2, ..., t_{n/2} və t_{n/2+1}, t_{n/2+2}, ..., t_n. Birinci hissəni massivində, ikinci hissəni isə massivində saxlayırıq.
Əvvəlcə ardıcıllığı üçün problemi həll edək. Onun bütün mümkün altməsələlərini seçək (onların sayı 2^{20} -dən çox olmayacaq). Hər altməsələ üçün onun elementlər cəmini hesablayırıq və hər belə cəm üçün dəyəri artırılır. Məlumat quruluşu kimi üçün unordered_map istifadə edilə bilər. Beləliklə, massivindən cəmi elementi olan altməsələni seçmənin sayı olacaq.
Sonra massivinin bütün altməsələlərini götürək. Götürək ki, həmin altməsələlərdən birinin elementlərinin cəmidir. Əgər bu altməsələni massivindən elementi s - sum olan bütün altməsələlərlə birləşdirərək, orijinal massivdən cəmi olan altməsələ alınırsa.
Nümunə
İkinci nümunəni nəzərdən keçirək. Giriş ardıcıllığını iki hissəyə bölək:
a = (1, 3, 2),
b = (2, 1, 4)
a = \{1, 3, 2\} dəstinin bütün altməsələlərini yoxlayaq:
\{1\}: sum = 1, m[1]++; | \{1, 2\}: sum = 3, m[3]++; |
\{3\}: sum = 3, m[3]++; | \{3, 2\}: sum = 5, m[5]++; |
\{2\}: sum = 2, m[2]++; | \{1, 3, 2\}: sum = 6, m[6]++; |
\{1, 3\}: sum = 4, m[4]++; | \{\}: sum = 0, m[0]++; |
məlumat quruluşu hissə dəstələrdən sonra aşağıdakı qiymətlərə malik olacaq:
İndi b = \{2, 1, 4\} dəstinin bütün altməsələlərini yoxlayaq. Bu nümunədə tələb olunan cəm s = 7 bərabərdir. Hər cəm üçün, , altməsələsinə uyğun olan, cavablara m[s - sum] dəyərini əlavə edəcəyik.
\{2\}: sum = 2, m[7 - 2] = m[5] = 1;
\{1\}: sum = 1, m[7 - 1] = m[6] = 1;
\{4\}: sum = 4, m[7 - 4] = m[3] = 2;
\{2, 1\}: sum = 3, m[7 - 3] = m[4] = 1;
\{2, 4\}: sum = 6, m[7 - 6] = m[1] = 1;
\{1, 4\}: sum = 5, m[7 - 5] = m[2] = 1;
\{2, 1, 4\}: sum = 7, m[7 - 7] = m[0] = 1;
\{\}: sum = 0, m[7 - 0] = m[7] = 0;
Axtarılan cəm 1 + 1 + 2 + 1 + 1 + 1 + 1 + 0 = 8, bu da cavabdır.
Alqoritmin implementasiyası
İş məlumat strukturlarını elan edək.
vector<int> a, b;
unordered_map<long long, long long> m;Giriş məlumatlarını oxuyuruq. Ardıcılın ilk yarısını massivinə, ikinci yarısını isə massivinə daxil edirik.
scanf("%d %d", &n, &s);
a.resize(n / 2);
for (i = 0; i < n / 2; i++)
scanf("%d", &a[i]);
b.resize(n - n / 2);
for (i = n / 2; i < n; i++)
scanf("%d", &b[i - n / 2]);ardıcıllığının bütün altməchullarını yoxlayırıq və onların elementlərinin cəmini hesablayırıq. unordered_map quruluşunda, bu altməchullar arasında hər bir cəmin neçə dəfə tapıldığını saxlayırıq. Əgər cari altmëxullanın cəmidir, dəyərini artırırıq.
for (i = 0; i < (1 << a.size()); i++)
{
sum = 0;dəyişəni cari altməxullunun bit maskasını ehtiva edir. Onun elementlərinin cəmi dəyişənində hesablanır.
for (j = 0; j < a.size(); j++)
if (i & (1 << j)) sum += a[j];Tapılmış hər cəm üçün dəyərini artırırıq.
m[sum]++;
}Orijinal massivin elementlərindən cəmi əldə etməyin yollarını dəyişənində sayırıq.
res = 0;ardıcıllığının bütün altməchullarını yoxlayırıq.
for (i = 0; i < (1 << b.size()); i++)
{
sum = 0;dəyişəni cari altməxullunun bit maskasını ehtiva edir. Bu altməxullunun elementlərinin cəmi dəyişənində hesablanır.
for (j = 0; j < b.size(); j++)
if (i & (1 << j)) sum += b[j];Əgər dəstinin cəm elementləri olan cari altməchuları, s - sum cəm elementləri olan bütün altməchuları ilə birləşdirilsə, cəmi olan bir altməchulaq əldə edilir.
if (m.count(s - sum) > 0) res += m[s - sum];
}Cavabı çıxışa yazırıq.
printf("%lld\n", res);