版权声明:代码属于原创,转载请联系作者并注明出处。 https://blog.csdn.net/weixin_43379056/article/details/85168825
Problem 58 : Spiral primes
Starting with 1 and spiralling anticlockwise in the following way, a square spiral with side length 7 is formed.
It is interesting to note that the odd squares lie along the bottom right diagonal, but what is more interesting is that 8 out of the 13 numbers lying along both diagonals are prime; that is, a ratio of 8/13 ≈ 62%.
If one complete new layer is wrapped around the spiral above, a square spiral with side length 9 will be formed. If this process is continued, what is the side length of the square spiral for which the ratio of primes along both diagonals first falls below 10%?
C++代码
#include <iostream>
#include <cmath>
#include <cassert>
using namespace std;
class PE0058
{
private:
bool checkPrime(long long number);
int getSquareSpiralPrimes(int number);
int getNewSpiralPrimes(int n);
int getNumbersLyingaLongBothDiagonals(int n);
public:
int getSideLengthOfSquareSpiral();
};
// try to find the law of the numbers:
//
// lower right corner:(2n+1)^2, e.g. n=2, 25, n=3, 49
//
// lower left corner: (2n+1)^2 - 2*n,e.g. n=2, 21, n=3, 43
//
// top left corner: (2n+1)^2-4*n, e.g. n=2, 17, n=3, 37
//
// top right corner: (2n+1)^2-6*n, e.g. n=2, 13, n=3, 31
//
bool PE0058::checkPrime(long long number)
{
long double squareRoot=sqrt((long double)number);
if (number < 2 || number % 2 == 0 && number != 2)
{
return false;
}
for(int i=3;i<=(long long)squareRoot;i+=2) // 3, 5, 7, ...(int)squareRoot
{
if (number % i == 0)
{
return false;
}
}
return true;
}
int PE0058::getSquareSpiralPrimes(int number)
{
int spiral_primes = 0;
for(int n=1; n<=number; n++)
{
spiral_primes += getNewSpiralPrimes(n);
}
return spiral_primes;
}
int PE0058::getNewSpiralPrimes(int n)
{
long long tmp_square;
int new_spiral_primes = 0;
tmp_square = (2*n+1)*(2*n+1);
// lower right corner: (2n+1)^2, e.g. n=2, 25, n=3, 49
// tmp_square is not prime
// lower left corner: (2n+1)^2 - 2*n, e.g. n=2, 21, n=3, 43
if (true == checkPrime(tmp_square - 2*n))
{
new_spiral_primes++;
}
// top left corner: (2n+1)^2-4*n, e.g. n=2, 17, n=3, 37
if (true == checkPrime(tmp_square - 4*n))
{
new_spiral_primes++;
}
// top right corner: (2n+1)^2-6*n, e.g. n=2, 13, n=3, 31
if (true == checkPrime(tmp_square - 6*n))
{
new_spiral_primes++;
}
return new_spiral_primes;
}
int PE0058::getNumbersLyingaLongBothDiagonals(int n)
{
int number = 1; // the first number is 1
number += 4*n; // number = 4*n + 1
return number;
}
int PE0058::getSideLengthOfSquareSpiral()
{
int numOfSpiralPrimes = getSquareSpiralPrimes(3); // 2*3+1 = 7
int numOfNumbers = getNumbersLyingaLongBothDiagonals(3);
assert(8 == numOfSpiralPrimes && 13 == numOfNumbers);
int n = 4;
while(1)
{
numOfSpiralPrimes += getNewSpiralPrimes(n);
numOfNumbers = getNumbersLyingaLongBothDiagonals(n);
if (numOfNumbers > numOfSpiralPrimes*10)
{
cout << "The side length of the square spiral is " << 2*n+1;
cout << " for which the ratio of primes" << endl;
cout <<"along both diagonals first falls below 10%, and the ratio";
cout<<" is "<<(numOfSpiralPrimes*100)/(numOfNumbers*1.0)<<"%"<<endl;
break;
}
n++;
}
return 2*n+1;
}
int main()
{
PE0058 pe0058;
pe0058.getSideLengthOfSquareSpiral();
return 0;
}
Python 代码
def checkPrime(x):
"""
check if number is a prime
"""
if (x < 2) or (x != 2 and x%2 == 0):
return False
for i in range (3, int(x**0.5)+1, 2):
if 0 == x % i:
return False
return True
def getSquareSpiralPrimes(number):
spiral_primes = 0
for n in range(1, number+1):
spiral_primes += getNewSpiralPrimes(n)
return spiral_primes
def getNewSpiralPrimes(n):
new_spiral_primes = 0
tmp_square = (2*n+1)*(2*n+1);
# lower right corner: (2n+1)^2, e.g. n=2, 25, n=3, 49
# tmp_square is not prime
# lower left corner: (2n+1)^2 - 2*n, e.g. n=2, 21, n=3, 43
if True == checkPrime(tmp_square - 2*n):
new_spiral_primes += 1
# top left corner: (2n+1)^2-4*n, e.g. n=2, 17, n=3, 37
if True == checkPrime(tmp_square - 4*n):
new_spiral_primes += 1
# top right corner: (2n+1)^2-6*n, e.g. n=2, 13, n=3, 31
if True == checkPrime(tmp_square - 6*n):
new_spiral_primes += 1
return new_spiral_primes
def getNumbersLyingaLongBothDiagonals(n):
number = 1 # the first number is 1
number += 4*n # number = 4*n + 1
return number
def getSideLengthOfSquareSpiral():
numOfSpiralPrimes = getSquareSpiralPrimes(3) # 2*3+1 = 7
numOfNumbers = getNumbersLyingaLongBothDiagonals(3)
assert 8 == numOfSpiralPrimes and 13 == numOfNumbers
n = 4
while True:
numOfSpiralPrimes += getNewSpiralPrimes(n)
numOfNumbers = getNumbersLyingaLongBothDiagonals(n)
if numOfNumbers > numOfSpiralPrimes*10:
ratioOfPrimes = (numOfSpiralPrimes*1.0)/numOfNumbers
print("The side length of the square spiral is",2*n+1, end='')
print(" for which the ratio of primes")
print("along both diagonals first falls below 10%, ", end='')
print("and the ratio is %.4f%%." % (ratioOfPrimes*100) )
break
n += 1
return 2*n+1
def main():
getSideLengthOfSquareSpiral()
if __name__ == '__main__':
main()