Tutaq ki, m = 3k + 7. Onda tələb olunan ifadə aşağıdakı kimi yenidən yazıla bilər:
Vilson teoremi. Əgər sadə ədəddirsə, onda
Yəni
Buna görə də, əgər sadə ədəddirsə, onda \frac{(m-1)!+1}{m} tam ədəd olacaq.
Eyni zamanda
Onda bütün ifadə bərabərdir
Əgər tərkib ədəddirsə, onda
çünki soldakı vurğunlar arasında ədədinin bütün bölənləri mövcuddur.
Bu halda
ifadəsi tam olacaq.
Onda bütün ifadə bərabərdir
S_n-i hesablamaq üçün 1 \le k \le n şərtini ödəyən 3k + 7 formasında olan sadə ədədlərin sayını tapmaq kifayətdir.
Eratosthenes süzgəci vasitəsilə adlı bir massiv qururuq, burada:
Daha sonra massivindən istifadə edərək 3i + 7 formasında olan sadə ədədləri təmsil edən massivini qururuq:
İndi
Çoxlu testlər olduğuna görə, onlara sabit vaxtda cavab vermək üçün prefiks cəmləri qururuq:
İndi hər dəyəri üçün sadəcə -i çıxarmalıyıq.
Nümunə
Tutaq ki, m = 7 — sadə. Onda
Tutaq ki, m = 6 — tərkib. Onda
n = 10 üçün cavabı hesablayın. 3k + 7 formasında olan bütün ədədləri nəzərdən keçirək, burada 1 \le k \le 10. Onlar arasında sadə ədədləri seçin.
Göstərilən ədədlər arasında sadə ədəd var: və . Deməli, S_{10} = 4.
Alqoritmin implementasiyası
İş massivlərini elan edək. Çünki n \le 10^6, massivlərin ölçüsünü 3n + 7 = 3 \cdot 10^6 + 7 olaraq təyin etmək lazımdır.
#define MAX 3000010
char used[MAX], a[MAX];Init funksiyası Eratosthenes süzgəcini həyata keçirir. massivi sadə ədədlər haqqında məlumatları saxlayır:
massivi 3i + 7 formasında olan sadə ədədləri saxlayır:
void Init()
{
for (int i = 2; i < MAX; i++)
{
if (!used[i])
{
if ((i - 7) % 3 == 0)
a[(i - 7) / 3] = true;
if (i < sqrt(MAX))
for (int j = i * i; j < MAX; j += i)
used[j] = true;
}
}
}Proqramın əsas hissəsi. Massivləri doldururuq.
Init();massivi üçün prefiks cəmlərini hesablamaq:
for (int i = 2; i < MAX; ++i)
p[i] = p[i - 1] + a[i];sayda testləri ardıcıl işləyirik.
scanf("%d", &tests);
while (tests--)
{
scanf("%d", &n);Hər dəyəri üçün -i çıxarırıq.
printf("%d\n", p[n]);
}