Задача
Широко известна проблема Гольдбаха! Вот одна из её версий:
- Любое нечетное число больше [latex]17[/latex] можно записать в виде суммы трёх нечётных простых чисел;
- Любое чётное число больше [latex]6[/latex] можно записать в виде суммы двух нечётных простых чисел.
Если число чётное, то мы раскладываем его на суммы двух простых разных нечётных, а если нечётное — то на суммы трёх простых разных нечётных. Такой способ разложения для заданного [latex]N[/latex] назовём делением Гольдбаха и обозначим как [latex]G\left( N \right)[/latex].
Зная заданное число [latex]N[/latex], найти [latex]\left| G\left( N \right) \right| [/latex], т.е. количество различных [latex]G(N)[/latex].
Входные данные:
Входные данные содержат несколько тестовых случаев.
Каждый тест в отдельной строке содержит одно единственное число [latex]N \left( 1\le N\le 20000 \right) [/latex].
Ввод продолжается до конца входного файла.
Выходные данные:
Для каждого тестового случая вывести в отдельной строке одно число — найденное значение [latex]\left| G\left( N \right) \right| [/latex].
Тесты
№ | Входные данные | Выходные данные |
1 | 5 8 18 19 20 |
0 1 2 1 2 |
2 | 13 22 78 4 150 |
0 2 7 0 12 |
3 | 2000 | 37 |
4 | 6 8 17 19 337 |
0 1 0 1 195 |
Код программы
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
#include <iostream> #include <vector> #include <unordered_map> #include <cmath> using namespace std; bool prime (int x){ //функция для проверки простоты нечётного числа bool pr=true; for(int i=2; i<=sqrt(x);i++)if(!(x%i))pr=false; return pr; } int main() { vector <int> v,prime_v; unordered_map <int,bool> prime_m; int u,i,j,maxx=0; while(cin>>u){ v.push_back(u); maxx=max(maxx,u);//максимальное значение во входном потоке } for(i=3;i<=maxx;i+=2){ if(prime(i)){ prime_m[i]=true; prime_v.push_back(i); } } int *dp,k; dp = new int [maxx+1]; for(i=0;i<=maxx;i++)dp[i]=0; for(i=8;i<=maxx;i++){//заполняем массив значениями |G(i)| if(i%2){ for(j=0;(j<prime_v.size())&&(prime_v[j]<i);j++){ k=i-prime_v[j]; if(dp[k]){ dp[i]+=dp[k]; if((prime_m[k-prime_v[j]])&&((k-prime_v[j])!=prime_v[j]))--dp[i]; } } } else{ for(j=0;(j<prime_v.size())&&(prime_v[j]<(i/2));j++){ k=i-prime_v[j]; if(prime_m[k])dp[i]++; } } if(i%2)dp[i]/=3; } for(i=0;i<v.size();i++)cout<<dp[v[i]]<<'\n'; return 0; } |
Засчитанное решение на e-olymp.com
Решение
Поместим все тестовые случаи в вектор и найдём максимальное из данных чисел — [latex]max[/latex]. Затем найдём все нечётные простые числа меньшие [latex]max[/latex] (единственное чётное простое число — [latex]2[/latex]). Заведём массив размером [latex]max+1[/latex], [latex]i[/latex]-м элементом которого будет [latex]\left| G\left( i \right) \right| [/latex]. Тогда, если [latex]i[/latex]- чётное, то одно из слагаемых суммы [latex]a_{i}+b_{i}[/latex] двух простых разных нечётных чисел будем подбирать из найденных ранее простых нечётных чисел, но строго меньших [latex]\frac { i }{ 2 } [/latex], чтобы разбиения, отличающиеся только порядком следования частей считать равными, и выполнялось неравенство [latex]a_{i}\neq b_{i}[/latex]. Если разность [latex]i[/latex] и подобранного таким образом числа — нечётное простое число, то это деление Гольдбаха, тогда увеличиваем на единицу [latex]\left| G\left( i \right) \right| [/latex]. Если [latex]i[/latex] — нечётное, то [latex]a_{i}[/latex]из суммы [latex]a_{i}+b_{i}+c_{i}[/latex] трёх простых разных нечётных чисел будем подбирать из всех простых нечётных чисел строго меньших [latex]i[/latex]. Разностью [latex]i[/latex] и подобранного числа [latex]a_{i}[/latex] (разность двух нечётных) будет чётное число [latex]j[/latex], [latex]\left| G\left( j \right) \right| [/latex] мы уже нашли ранее. Тогда можем представить [latex]\left| G\left( j \right) \right| [/latex] различных разложений [latex]G\left( i \right)[/latex] в виде [latex]a_{i}+G\left( j \right)_{k}[/latex] или [latex]a_{i}+{a_j}_{k}+{b_j}_{k}[/latex], где [latex]k=\overline { 1,\left| G\left( j \right) \right| } [/latex], a [latex]G\left( j \right)_{k}[/latex] — [latex]k[/latex]-е разбиение числа [latex]j[/latex]. Значит все полученные [latex]\left| G\left( j \right) \right| [/latex] будем прибавлять к [latex]\left| G\left( i \right) \right| [/latex], а чтоб избежать ситуаций [latex]a_i={a_j}_k[/latex] и [latex]a_i={b_j}_k[/latex], если [latex]i-2a_{i}[/latex] — простое число не равное [latex]a_{i}[/latex] (то есть при некотором значении [latex]k[/latex] одно из чисел [latex] G\left( j \right)_{k} [/latex] равно [latex]a_{i}[/latex] и не равно второму числу, так как [latex]{a_{j}}_k\neq {b_{j}}_k[/latex] мы учли ранее), то будем отнимать единицу от [latex]\left| G\left( i \right) \right| [/latex]. В разбиениях [latex]j[/latex] мы не учитываем порядок следования частей. Чтобы не учитывать его в и разбиениях числа [latex]i[/latex], разделим полученный результат [latex]\left| G\left( i \right) \right| [/latex] на [latex]3[/latex].
Хорошо, зачтено.
Кстати, Вы не читали Апостолос Доксиадис.
Дядюшка Петрос и проблема Гольдбаха? Рекомендую. Вам должно понравиться.