SRM 365 300pt: PointsOnCircle
問題概要
原点中心半径r(<2*10^9)の円がある。円周上にある格子点の数を求める問題。
考えたこと
- 何か公式が与えられてるけどそれ使った解法がよく分からない。
- とりあえず数列辞典に投げてみよう。
- あった。色々調べたら、rの素因数で、4で割って1余るものの指数をa[i]とすると4*Π(1+2*a[i])が答えになるらしい。
- 後は素因数分解するだけ。
#include <stdio.h> #include <vector> #include <cstring> using namespace std; typedef long long int64; const int MAX_SIZE = 1<<18; bool isPrime[MAX_SIZE]; void seive(){ memset(isPrime, -1, sizeof(isPrime)); bool *ps = isPrime; ps[0] = ps[1] = false; for(int i=2; i*i<MAX_SIZE; i++)if(ps[i]){ for(int j=i<<1; j<MAX_SIZE; j+=i){ ps[j] = false; } } } struct PointsOnCircle { int64 count(int64 r){ seive(); return func(r); } int64 func(int64 n){ vector<int> ones; //4で割って1余る素因数の指数 for(int i=2; i*i<=n; i++)if(isPrime[i] && n%i==0){ int tmp = 0; while(n%i==0){ n /= i; tmp++; } if(i%4==1){ ones.push_back(tmp); } } if(n != 1 && n%4==1){ ones.push_back(1); } //4で割って1余る素数のべきが大事 int64 ret = 4; for(int i=0; i<(int)ones.size(); i++){ ret *= (1 + 2*ones[i]); } return ret; } };