@description@
令 p[] 为质数序列:p[0] = 2, p[1] = 3, p[2] = 5,以此类推。
令 D 为正整数常数。对于每一个 i >= 0,令 q[i] = q[i] * q[i + D]。
考虑等式 V + W + X + Y = Z。
现给定 N 与 D。统计上面等式的解的数量,同时要求 V <= W <= X <= Y 且所有量 V, W, X, Y, Z 都属于集合 Q = {q[0], q[1], ..., q[N-1]}。
Constraints
1 <= N <= 2500,0 <= D <= 2500。
Examples
0)
15
1
Returns: 2
两个解如下:
6 + 15 + 323 + 323 = 667
6 + 143 + 221 + 1147 = 1517
2470
0
Returns: 0
不存在任何解。
@solution@
假如等式是这样的:W + X + Y = Z。
我们可以变为 W + X = Z - Y,然后 meet in the middle 即可。
那么 5 个变量怎么办呢?注意还有一个条件:p 是质数。
质数有一个什么性质呢?比较复杂的性质当然不是我们分析的目标。我们只考虑质数的奇偶性。
奇偶分析一波,可以发现 5 个变量不可能同时为奇数。然而质数中只有 2 为偶数,所以相当于一定存在一个 2。
而又因为 2 是最小的那个质数,所以得到 V = 2*p[D]。
然后就可以愉快地 meet in the middle 了。
@accepted code@
#include<cstdio>
#include<vector>
#include<iostream>
using namespace std;
class Diophantine{
#define MAXN 2500
#define PRIME 60000
#define HASHSIZE 1000037
typedef long long ll;
typedef pair<ll, int> pii;
#define fi first
#define se second
private:
int prm[PRIME + 5], nprm[PRIME + 5], pcnt;
void sieve() {
for(int i=2;i<=PRIME;i++) {
if( !nprm[i] ) prm[pcnt++] = i;
for(int j=0;i*prm[j]<=PRIME;j++) {
nprm[i*prm[j]] = true;
if( i % prm[j] == 0 ) break;
}
}
}
vector<pii>hsh[HASHSIZE];
void hash_insert(ll x) {
int y = x % HASHSIZE;
for(int i=0;i<hsh[y].size();i++)
if( hsh[y][i].fi == x ) {
hsh[y][i].se++;
return ;
}
hsh[y].push_back(make_pair(x, 1));
}
int hash_search(ll x) {
int y = x % HASHSIZE;
for(int i=0;i<hsh[y].size();i++)
if( hsh[y][i].fi == x )
return hsh[y][i].se;
return 0;
}
public:
ll q[MAXN + 5];
int countSolutions(int N, int D) {
sieve();
for(int i=0;i<N;i++)
q[i] = prm[i] * prm[i + D];
int ans = 0;
for(int i=N-1;i>=0;i--) {
for(int j=i+1;j<N;j++)
if( q[j] - q[i] - q[0] > 0 )
hash_insert(q[j] - q[i] - q[0]);
for(int j=i;j>=0;j--)
ans += hash_search(q[i] + q[j]);
}
return ans;
}
};
@details@
一开始看错题了,还以为只有 4 个变量,然后就以为是 meet in the middle 的题。
结果发现是 5 个变量,然后修正一下想法就过了。
这算是。。。因祸得福吗。。。