• @topcoder



    @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 个变量,然后修正一下想法就过了。

    这算是。。。因祸得福吗。。。

  • 相关阅读:
    1012每日博客
    1011每日博客
    108每日博客
    1013每日博客
    1015每日博客
    写几个关于sql server的例子
    正则表达式实例
    gridview 选中行变色
    ASP.NET跨页面传值技巧
    关于不同电脑Outlook同步
  • 原文地址:https://www.cnblogs.com/Tiw-Air-OAO/p/11622489.html
Copyright © 2020-2023  润新知