При условии равномерной встречаемости букв с точностью до одного бита оцените количество информации, содержащееся в последовательности ДНК длиной 800 нуклеотидов
#include<stdio.h> int main(){ int div[10001]; int i,d,n,x; long int p = 1;
for(i = 0; i < 10000; i++) div[i] = 1;
scanf("%d",&n); for(i = 0; i < n; i++){ scanf("%d",&x); d = 2; while(d <= x){ while(x%d == 0){ x /= d; div[d]++; } d++; } }
for(i = 0; i < 10000; i++) p *= div[i]; printf("%ld",p); return 0; }
/* Небольшое пояснение: Идея решения заключается в том, что любой делитель результата представим как произведение простых чисел в определенных степенях. Тогда набор этих степеней однозначно определяет соответствующий делитель. Максимальная степень, с которой может быть взято простое число, является суммой степеней, с которыми оно входит в множители. Для простоты массив вхождений делителей задан от 0 до 10000, но т.к. перебор делителей множителей идет по возрастанию, учтены будут только простые делители.
Пример: 10 * 8 * 9 = 720
10 = 2^1*5^2 8 = 2^3 9 = 3^2
Т.е. число 2 входит в произведение в четвертой степени, 3 - во второй, 5 - в первой.
Значит любой делитель числа 720 представим (единственным образом) в виде 2^(d2) * 3^(d3) * 5^(d5), где d2 = 0..4, d3 = 0..2, d5 = 0..1
// PascalABC.NET 3.2, сборка 1439 от 09.05.2017
// Внимание! Если программа не работает, обновите версию!
begin
SeqRandom(10,-10,20).Select(x->(x,1/x)).Println(NewLine)
end.
Пример
(13,0.0769230769230769)
(-10,-0.1)
(9,0.111111111111111)
(-5,-0.2)
(14,0.0714285714285714)
(18,0.0555555555555556)
(15,0.0666666666666667)
(3,0.333333333333333)
(-5,-0.2)
(-9,-0.111111111111111)
2. "Красивый" вариант
// PascalABC.NET 3.2, сборка 1439 от 09.05.2017
// Внимание! Если программа не работает, обновите версию!
begin
SeqRandom(10,-10,20).Select(x->(x,1/x))
.Foreach(x->Writeln(x[0]:3,x[1]:15:8))
end.
Пример
18 0.05555556
-10 -0.10000000
16 0.06250000
6 0.16666667
15 0.06666667
13 0.07692308
5 0.20000000
18 0.05555556
-1 -1.00000000
13 0.07692308
3. А так писали наши деды четверть века назад...
var
i,x:integer;
begin
Randomize;
for i:=1 to 10 do begin
x:=Random(31)-10;
Writeln(x:3,1/x:15:8)
end
end.
Пример
-7 -0.14285714
11 0.09090909
-2 -0.50000000
-10 -0.10000000
14 0.07142857
-7 -0.14285714
-5 -0.20000000
5 0.20000000
13 0.07692308
10 0.10000000
int main(){
int div[10001];
int i,d,n,x;
long int p = 1;
for(i = 0; i < 10000; i++)
div[i] = 1;
scanf("%d",&n);
for(i = 0; i < n; i++){
scanf("%d",&x);
d = 2;
while(d <= x){
while(x%d == 0){
x /= d;
div[d]++;
}
d++;
}
}
for(i = 0; i < 10000; i++)
p *= div[i];
printf("%ld",p);
return 0;
}
/*
Небольшое пояснение:
Идея решения заключается в том, что любой делитель результата представим как произведение простых чисел в определенных степенях. Тогда набор этих степеней однозначно определяет соответствующий делитель. Максимальная степень, с которой может быть взято простое число, является суммой степеней, с которыми оно входит в множители.
Для простоты массив вхождений делителей задан от 0 до 10000, но т.к. перебор делителей множителей идет по возрастанию, учтены будут только простые делители.
Пример:
10 * 8 * 9 = 720
10 = 2^1*5^2
8 = 2^3
9 = 3^2
Т.е. число 2 входит в произведение в четвертой степени, 3 - во второй, 5 - в первой.
Значит любой делитель числа 720 представим (единственным образом) в виде
2^(d2) * 3^(d3) * 5^(d5), где d2 = 0..4, d3 = 0..2, d5 = 0..1
Например, 1 = 2^0 * 3^0 * 5^0, 720 = 2^4 * 3^2 * 5^1
Есть выбрать выбрать d3 и выбрать d5 --> всего 5 * 3 * 2 = 30 возможных наборов --> 30 делителей у числа 720
(если какое-то число не появляется среди делителей множителей, то его можно взять только одним со степенью 0 - что не влияет на ответ)
*/