[c] liczby pierwsze
-
- Użytkownik
- Posty: 1676
- Rejestracja: 2 kwie 2007, o 14:43
- Płeć: Mężczyzna
- Lokalizacja: warszawa
- Podziękował: 178 razy
- Pomógł: 17 razy
[c] liczby pierwsze
jak napisac program .który znajduje wszystkie liczby pierwsze w zakresie 30 do 30000 takie, że zarówno
suma, jak i iloczyn ich cyfr są również liczbami pierwszymi. z góry dzieki
suma, jak i iloczyn ich cyfr są również liczbami pierwszymi. z góry dzieki
-
- Użytkownik
- Posty: 941
- Rejestracja: 17 gru 2007, o 21:48
- Płeć: Mężczyzna
- Lokalizacja: Kingdom Hearts
- Podziękował: 6 razy
- Pomógł: 222 razy
[c] liczby pierwsze
Kod: Zaznacz cały
#include <stdio.h>
int tablica[30001];
int ok(int i)
{
int t[5],w=0,s=i,k,suma=0,iloczyn=1;
while(s>0)
{
t[w]=s%10;
s/=10;
w++;
}
for(k=0;k<w;k++)
{
suma+=t[k];
iloczyn*=t[k];
}
return (tablica[suma]&&tablica[iloczyn]);
}
int main()
{
int i,j,t;
for(i=1;i<=30000;i++) tablica[i]=1;
for (i=2; i<=30000; i++)
{
if (tablica[i])
{
j = 2*i;
while (j<=30000)
{
tablica[j] = 0;
j += i;
}
}
}
for(i=30;i<30001;i++)
if(tablica[i]&&ok(i)) printf("%d
",i);
return 0;
}
[c] liczby pierwsze
Kod: Zaznacz cały
for(i=3;i<=30000;i++) tablica[i]=i & 1;
tablica[2]=1; tablica[0]=tablica[1]=0;
for (i=2; i<=173; i++)
if (tablica[i]) {
j = i*i;
while (j<=30000) {
tablica[j] = 0;
j += i;
}
}
-
- Użytkownik
- Posty: 735
- Rejestracja: 7 lis 2005, o 23:56
- Płeć: Mężczyzna
- Lokalizacja: Łódź
- Podziękował: 2 razy
- Pomógł: 133 razy
[c] liczby pierwsze
Akurat tutaj to jest dużo prostsze. Skoro iloczyn cyfr ma być liczbą pierwszą to conajwyżej jedna cyfra może nie być jedynką. Tak więc mamy do sprawdzenia tylko kilkadziesiąt (może ze 150 max) liczb. Jeśli jako pierwsze sprawdzimy, czy suma cyfr jest pierwsza, potem to samo z iloczynem a na koniec samą liczbę to program wykona się kilkadziesiąt razy szybciej niż przy sicie eratostenesa.
[c] liczby pierwsze
Przy małym zakresie Sito jest jednak dobrym sposobem
W 70 sekund znalazłem 49 takich liczb, doszedłem do 112'111'111'111'111'111.
W 70 sekund znalazłem 49 takich liczb, doszedłem do 112'111'111'111'111'111.
Kod: Zaznacz cały
#include <stdio.h>
int isprime(unsigned long long int n){ // poprawka, dodałem "long long"
unsigned int d;
if (n<2) return 0;
if (n<4) return 1;
if (n%2==0 || n%3==0) return 0;
d=5;
while((unsigned long long int)d*d<=n){
if (n%d==0) return 0;
d+=2;
if (n%d==0) return 0;
d+=4;
}
return 1;
}
void g(int i, int p){
unsigned long long s;
int k,j;
if(isprime(p+i))
for(j=0; j<=i; j++) {
s=0;
for(k=i; k>=0; k--)
if(k==j) s=s*10+p;
else s=s*10+1;
if (/*s<=30000 &&*/ isprime(s))
printf("%I64d ", s);
}
}
int main(){
int i;
for(i=0; i<18; i++) {
if(i==0) g(0,2);
if(i&1) g(i, 2);
else {
g(i, 3);
g(i, 5);
g(i, 7);
}
}
while(1);
}
Ostatnio zmieniony 11 maja 2009, o 20:12 przez Xitami, łącznie zmieniany 2 razy.
-
- Użytkownik
- Posty: 735
- Rejestracja: 7 lis 2005, o 23:56
- Płeć: Mężczyzna
- Lokalizacja: Łódź
- Podziękował: 2 razy
- Pomógł: 133 razy
[c] liczby pierwsze
Moim zdaniem można to troszkę podrasować. Napisałem w C++, łatwo można zmienić zakres - program wyszukuje pierwsze 155 takich liczb, zajmuje mu to 0,15s:
Kod: Zaznacz cały
#include <cstdlib>
#include <iostream>
#include <ctime>
using namespace std;
const int nieparzyste[] = {1, 3, 5, 7};
bool czyPierwsza(int liczba)
{
for(int i = 2; i*i <= liczba; i++)
if(liczba % i == 0)
return false;
return true;
}
int main(int argc, char *argv[])
{
long czas = clock();
int licznik = 0;
for(int i = 2; i < 20; i++)
for(int j = 0; j < i; j++)
if(i%2 == 0)
{
long long liczba = 0;
for(int l = 0; l < i; l++)
{
liczba *= 10;
if(l == j) liczba += 2;
else liczba += 1;
}
if(czyPierwsza(i+1) && czyPierwsza(liczba))
{
cout << liczba << endl;
licznik++;
}
} else
for(int k = 0; k < 4; k++)
{
long long liczba = 0;
for(int l = 0; l < i; l++)
{
liczba *= 10;
if(l == j) liczba += nieparzyste[k];
else liczba += 1;
}
if(czyPierwsza(i - 1 + nieparzyste[k]) && czyPierwsza(liczba))
{
cout << liczba << endl;
licznik++;
}
}
czas = clock() - czas;
float s = static_cast<float>(czas) / CLOCKS_PER_SEC;
cout << "Znalazlem " << licznik << " liczb" << endl;
cout << "Zejelo mi to " << s << " sekund" << endl;
system("PAUSE>>null");
return EXIT_SUCCESS;
}
[c] liczby pierwsze
Jeszcze nie przeczytałem do końca, ale...
isprime(111111111121111111) == 0
a rozumiem, że powinna być pierwsza
Dla wszystkich odpowiednich liczb (pierwsza suma i iloczyn cyfr), poza dwójką,
wystarczy sprawdzić czy 2 jest świadkiem w teście Rabina-Millera
(sprawdziłem do 1e100),
mam takiego cosia teoretycznie liczy a^b%n, a,b,n<2^60, czyli można by przyśpieszyć.
Ale coś nie chce działać.
49 liczb, tyle mieści się w long long int.
zmieniłem trochę swój kod, teraz 62 sekundy
już wiem, poprawiłem twoją funkcję Popatrz jak ja to robię, jestem jakieś 3 razy szybszy
isprime(111111111121111111) == 0
a rozumiem, że powinna być pierwsza
Dla wszystkich odpowiednich liczb (pierwsza suma i iloczyn cyfr), poza dwójką,
wystarczy sprawdzić czy 2 jest świadkiem w teście Rabina-Millera
(sprawdziłem do 1e100),
mam takiego cosia
Kod: Zaznacz cały
uint64 mul_mod1(uint64 a, uint64 b, uint64 m) {
uint64 y = (uint64)((float64)a*(float64)b/m+(float64)1/2); // floor(a*b/m)
y = y * m; // m*floor(a*b/m) mod z
uint64 x = a * b; // a*b mod z
uint64 r = x - y; // a*b mod z - m*floor(a*b/m) mod z
if ( (int64)r < 0 ) // normalization needed ?
{
r = r + m;
y = y - 1; // (a*b)/m quotient, omit line if not needed
}
return r; // (a*b)%m remnant
}
Ale coś nie chce działać.
49 liczb, tyle mieści się w long long int.
- 2,3,5,7,113,131,311,151,2111, 11113, 11131, 11311, 11117, 11171, 111121, 111211, 112111, 1111151, 1111711, 1117111,
1171111, 111111113, 111111131, 111113111, 131111111, 115111111, 1111111121, 1111211111, 1121111111, 11111111113,
11111111131, 11113111111, 11131111111, 31111111111, 17111111111, 111111211111, 111211111111, 1111151111111,
5111111111111, 1111171111111, 111111151111111, 111151111111111, 11111111113111111, 11111111111111171,
11111111171111111, 111111111111112111, 111111112111111111, 111111211111111111, 112111111111111111
zmieniłem trochę swój kod, teraz 62 sekundy
Kod: Zaznacz cały
void g(int i, uint64 j, uint64 p){
uint64 w;
int k;
if(isprime(p+i)) {
k=i; w=p;
while(k>0) {
w*=10; k--;
}
p--;
while(w>p) {
if(isprime(p+j)) {
printf("%19I64d ", p+j);
m++;
}
p*= 10;
}
}
}
int main(){
unsigned int i,c;
uint64 j;
c=clock(); m=0;
j=1;
for(i=0; i<10; i++) {
//printf("
(%d) ",i);
if(i==0) g(0, j, 2);
if(i &1) g(i, j, 2);
else {
g(i, j, 3);
g(i, j, 5);
g(i, j, 7);
}
j=j*10+1;
}
c=clock()-c;
printf("
koniec
%d sztuk
%4d.%03d sekund",m,c/1000,c%100);while(1);
}
Kod: Zaznacz cały
bool czyPierwsza(long long int liczba)
{
for(int i = 2; (unsigned long long int)i*i <= liczba; i++)
if(liczba % i == 0)
return false;
return true;
}
-
- Użytkownik
- Posty: 735
- Rejestracja: 7 lis 2005, o 23:56
- Płeć: Mężczyzna
- Lokalizacja: Łódź
- Podziękował: 2 razy
- Pomógł: 133 razy
[c] liczby pierwsze
Znam kilka testów pierwszości, natomiast chodziło mi tu o to, że program można baaaaardzo przyspieszyć zauważając kilka prostych rzeczy - moja wersja działa tak, że generuje jedynie liczby pewnej postaci (posiadające poza jedynką max jedną cyfrę - do tego nie sprawdzam wszystkich możliwych cyfry). Następnie dla każdej tak utworzonej liczby sprawdzam, czy suma jej cyfr jest pierwsza. Dopiero ostatnie sprawdzenie to sprawdzenie pierwszości tej liczby - wykonuje się ono (w przedziale 30-30000) kilkadziesiąt razy, więc to działa bardzo szybko.
Co do zakresu - nie wiem, eksperymentowałem. Na pewno więcej już przekracza zakres.
Co do zakresu - nie wiem, eksperymentowałem. Na pewno więcej już przekracza zakres.
[c] liczby pierwsze
Zauważ, że robię tak samo.
Nie pomijam 2, 3, 5, 7, ale to drobiazg.
Popraw for(int i = 2; i < 20; i++) na for(int i = 2; i < 19; i++) tyle można dla long long.
po zmianie testu pierwszości na mój, twój program liczy minimalnie wolniej, 65 sekund.
Nie pomijam 2, 3, 5, 7, ale to drobiazg.
Popraw for(int i = 2; i < 20; i++) na for(int i = 2; i < 19; i++) tyle można dla long long.
po zmianie testu pierwszości na mój, twój program liczy minimalnie wolniej, 65 sekund.