每一个数都能表示成质数的乘积。
const long numm = 600851475143;
long newnumm = numm;
long largestFact = 0;
int counter = 2;
while (counter * counter < newnumm) {
if (newnumm % counter == 0) {
newnumm = newnumm / counter;
largestFact = counter;
} else {
counter++;
}
}
if (newnumm > largestFact) { // the remainder is a prime number
largestFact = newnumm;
}
我觉得这个方法不错,用bitset,先每位置1,假设全为质数,然后一个一个的置0,以质数的2倍开始置0,以该质数递增。如4,6,8置0,然后6,9置0,一直循环置0,直到其他为1的全为质数。
#include [lt]iostream[gt]
#include [lt]bitset[gt]
using namespace std;
int main()
{
bitset[lt]1000000[gt] Sieve;
__int64 sum = 0;
Sieve.flip(); // Set all bits to 1
Sieve[0].flip(); // Set 0 and 1 to not prime
Sieve[1].flip();
// Check all nos from 2 to 1 million
for(long i = 2; i < 1000000; ++i)
{
if( ! Sieve[i] ) // If marked not prime
continue; // return to head of loop
else
// Set all multiples as not prime
for(long j = 2*i; j < 1000000; j += i)
Sieve[j] = 0;
}
for(long i = 2; i < 1000000; ++i)
if( Sieve[i] ) // Add all nos with bit set
sum += i;
cout << "\nThe sum is : " << sum << endl;
return 0;
}
每个数都能表示为N个质数的乘积。
求因子数
private int NumberOfDivisors(int number) {
int nod = 0;
int sqrt = (int) Math.Sqrt(number);
for(int i = 1; i<= sqrt; i++){
if(number % i == 0){
nod += 2;
}
}
//Correction if the number is a perfect square
if (sqrt * sqrt == number) {
nod--;
}
return nod;
}
Any number N is uniquely described by its prime factorisation
Where pn is the a distinct prime number, an is the exponent of the prime and K is the set of all prime numbers less than or equal to the square root of N. Taking any unique combination of the prime factors and multiplying them, will yield a unique divisor of N. That means we can use combinatorics to determine the number of divisors based on the prime factorisation. The prime pncan be chosen 0,1,…,an times. That means in all we can choose pn in an+1 different ways.
The total number of divisors of N , D(N) can be expressed as
其中an为每个质数的指数。即得以前计算因子数的函数。
private int PrimeFactorisationNoD(int number, int[] primelist) {
int nod = 1;
int exponent;
int remain = number;
for (int i = 0; i < primelist.Length; i++) {
// In case there is a remainder this is a prime factor as well
// The exponent of that factor is 1
if (primelist[i] * primelist[i] > number) {
return nod * 2;
}
exponent = 1;
while (remain % primelist[i] == 0) {
exponent++;
remain = remain / primelist[i];
}
nod *= exponent;
//If there is no remainder, return the count
if (remain == 1) {
return nod;
}
}
return nod;
}
n n/2 (n is even) n 3n + 1 (n is odd)))
用caching可以减少运行时间,从小到大查找,cache都记录了,每个数到1的步数,所以当数小于自己时,可以用cache查处步数,直接算出。
代码如:
for (int i = 2; i <= number; i++) {
sequence = i;
int k = 0;
while (sequence != 1 && sequence >= i) {//等于1或小于自己时停止(因为小于自己的数的步数都已经算出来)
k++;
if ((sequence % 2) == 0) {
sequence = sequence / 2;
} else {
sequence = sequence * 3 + 1;
}
}
//Store result in cache利用cache算出步数(cache[1] = 1)
cache[i] = k + cache[sequence];
//Check if sequence is the best solution
if (cache[i] > sequenceLength) {
sequenceLength = cache[i];
startingNumber = i;
}
}
How many such routes are there through a 2020 grid?
递加上去,直到顶点
可以用笔算
There is no particular pattern in the first numbers, so all we can do is spell them out and count them.
3 + 3 + 5 +4 + 4 +3 +5 +5 +4 = 36
There is also too little pattern in the next 10 numbers that I want to make a deal out of it, so if we count those as well we get
3 + 6 + 6 + 8 + 8 + 7 + 7 + 9 + 8 + 8 = 70
Now a pattern starts emerging. For each period of ten numbers, we have a prefix 10 times and then the sequence 1-9, which we have already counted. So we need to figure out how many letters the tens contain and add 8*36.
10*(6 + 6 + 5 + 5 + 5 + 7 + 6 + 6) + 8*36 = 748
So if we sum that up the number 1-99 will contain 36 + 70 + 74 8= 854 letters
We will use sort of the same trick here.
If we look at one hundred and twenty two (122) and four hundred and fifty three (453). We will see that the number 1-9 is prepended, then comes the words “hundred and” (10 letters), and last comes a number between 1 and 99. Whole hundreds such as two hundred (200) are a special case where you have the numbers 1-9 followed by “hundred” (7 letters).
If we break it down we have the numbers 1-9 occurring 100 times each. => 36*100 = 3600
1-99 occurring 9 times => 9*854 = 7686
We have “hundred” occurring 9 times with 7 letters. => 7*9 = 63
We have “hundred and” occurring 9*99 times with 10 letters => 9*99*10 = 8910
So in total we have
3600 + 7686 + 63 + 8910= 20259 +11
3
7 4
2 4 6
8 5 9 3
底层往上加。
3
7 4
10 13 15
3
20 19
0 | 1 | 2 | 3 | 4 | 5 |
1 | 1 | 0 | 0 | 0 | 0 |
0 | 1 | 2 | 3 | 4 | 5 |
1 | 1 | 1 | 1 | 1 | 1 |
0 | 1 | 2 | 3 | 4 | 5 |
1 | 1 | 2 | 1 | 1 | 1 |
0 | 1 | 2 | 3 | 4 | 5 |
1 | 1 | 2 | 2 | 1 | 1 |
0 | 1 | 2 | 3 | 4 | 5 |
1 | 1 | 2 | 2 | 3 | 1 |
0 | 1 | 2 | 3 | 4 | 5 |
1 | 1 | 2 | 2 | 3 | 3 |
int target = 200;
int[] coinSizes = { 1, 2, 5, 10, 20, 50, 100, 200 };
int[] ways = new int[target+1];
ways[0] = 1;
for (int i = 0; i < coinSizes.Length; i++) {
for (int j = coinSizes[i]; j <= target; j++) {
ways[j] += ways[j - coinSizes[i]];
}
}
计算公式
,最后当p*p >n时,t(n) *= (n + 1),即左边等式
两个互质的数:
计算因子和代码:(因为不包含数本身,最后要减去)
private int sumOfFactorsPrime(int number, int[] primelist) {
int n = number;
int sum = 1;
int p = primelist[0];
int j;
int i = 0;
while (p * p <= n && n > 1 && i < primelist.Length) {
p = primelist[i];
i++;
if (n % p == 0) {
j = p * p;
n = n / p;
while (n % p == 0) {
j = j * p;
n = n / p;
}
sum = sum * (j - 1) / (p - 1);
}
}
//A prime factor larger than the square root remains
if (n > 1) {
sum *= n + 1;
}
return sum - number;
}
The obvious best choice would be to find a prime number close to 10.000.000. However, that is not possible since a prime must end in 1,3,7,9 and φ(n) = n-1 would only change the last digit. So they cannot be permutations of each other.一个数的话,不可能会出现φ(n)和n会是同一个排序序列。
The next best thing is two distinct prime factors where each is close to . So if we just search number which are products of primes between 2000 and 5000 then there should be a good chance that we hit the one we are looking for.
公式:(表示n为p1*p2,两个质数之积)
We can multiply phi with and with and get
Since we get
We can multiply and into the fractions and get
根据等式
其中,p/q是当前在求的分式,a/b是上限,即3/7.q是从100万开始递减
还有
其中r/s是当前存的最接近a/b的分式,如果满足上述等式,用p,q替换r,s。
int limit = 1000000;
int[] phi = Enumerable.Range(0, limit+1).ToArray();
long result = 0;
for(int i = 2; i <= limit; i++){
if (phi[i] == i) {
for (int j = i; j <= limit; j += i) {
phi[j] = phi[j] / i * (i - 1);
}
}
result += phi[i];
}
其中a/b 为下限(开始为1/3,即前一值,之后替换为c/d),c/d为上限(开始为4000/11999,下一值,之后替换为e/f,最终为1/2)。e/f为中间的值。n为序列长度。
先把0到9的阶乘存于数组中,便于计算和节省时间。
用缓存,保存已经计算过到重复数据的数量,算出阶乘和后判断是否已经计算。其中的实现中list可以用vector替换(set其中存储是有序的,不能用于替换list,即不是按顺序存放,是按从小到大排序的)
int limit = 1000000;
int result = 0;
int[] seqlengths = new int[limit+1];
seqlengths[169] = 3;
seqlengths[363601] = 3;
seqlengths[1454] = 3;
seqlengths[871] = 2;
seqlengths[45361] = 2;
seqlengths[872] = 2;
seqlengths[45362] = 2;
for (int i = 1; i <= limit; i++) {
int n = i;
int count = 0;
List seq = new List();
seq.Add(0);
while (seq[seq.Count-1] != n) {
seq.Add(n);
n = FacSum(n);
count++;
if(n <= limit && seqlengths[n] > 0){
count += seqlengths[n];
break;
}
}
if (count == 60) result++;
for (int j = 1; j < seq.Count; j++) {
if (seq[j] <= limit) seqlengths[seq[j]] = count;
count--;
}
}
p(5)=7.
OOOOO |
OOOO O |
OOO OO |
OOO O O |
OO OO O |
OO O O O |
O O O O O |
|
int[,] grid = readInput(filename);
int gridSize = grid.GetLength(0);
int[] sol = new int[gridSize];
//initialise solution
for (int i = 0; i < gridSize; i++) {
sol[i] = grid[i, gridSize - 1];
}
for (int i = gridSize - 2; i >= 0; i--) {
// Traverse down
sol[0] += grid[0, i];
for (int j = 1; j < gridSize; j++) {
sol[j] = Math.Min(sol[j - 1] + grid[j, i], sol[j] + grid[j, i]);
}
//Traverse up
for (int j = gridSize - 2; j >= 0; j--) {
sol[j] = Math.Min(sol[j], sol[j+1] + grid[j,i]);
}
}
这个是有18个矩形,面积为6;
求有多少个矩形的代码:
int rectangles(int x, int y) {
int rects = 0;
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
rects += (x - i) * (y - j);
}
}
return rects;
}
还有一中优化方法,宽为X,则有X+1个点,从中选2个点,长为Y,则有Y+1个点,从中选2个点,一起组成一个矩形,则可能的情况有
,计算出后为矩形的数量。由公式,可以计算,
即得
所以矩形的数量可以直接用公式X*(X+1)*Y*(Y+1)/4算得。
即代码可以为(其中error为上限值,开始为int的最大值(32位的),当总数大于目标数量target时,减少x,否则增加y)
int error = int.MaxValue;
int closestarea = 0;
int target = 2000000;
int x = 2000;
int y = 1;
while (x >= y) {
int rects = x * (x + 1) * y * (y + 1) / 4;
if (error > Math.Abs(rects - target)) {
closestarea = x * y;
error = Math.Abs(rects - target);
}
if (rects > target)
x--;
else
y++;
}
直接替换字符串"VIIII",“LXXXX”,"DCCCC"."IIII","XXXX","CCCC"到"kk",因为不用实际计算罗马数的结果,直接把前面6种情况都替换成“kk”不影响结果,实现的话,我就是用find,然后在replace,待所有都替换完后,计算减少字符的数量,代码大概如下:(也没找到更好的替换方法)其中,string::npos表示没有找到。
if((pos = rep.find("LXXXX")) != string::npos)
{
rep.replace(pos,5,"kk");
}
方法就是先求出该3点组成的三角形的面积,然后计算原点与其中2点组成的面积,然后计算与原点组成的三角形面积之和是否等于3点组成面积,如果是,则表明,原点在其内。
计算面积公式
我觉得还可以用余弦公式来计算由原点到其中2点的角度,如果3个角度之和等于360度,则在其内,不过求角度有写麻烦,要先求出cos的值(用余弦公式
),然后还要转换成角度(可以用cmah中的反余弦函数acos求出)。算百分比可以不用浮点型数,直接用整型,百分比乘以100即可,如100*bouncies < 99*i,其中bouncies为bouncy数数量,i为总数,99为比例
判断是否为bouncy,即判断数既不递增也不递减,用两个bool类型变量即可。