码迷,mamicode.com
首页 > 其他好文 > 详细

表为平方和终极版

时间:2015-02-21 18:51:59      阅读:236      评论:0      收藏:0      [点我收藏+]

标签:

声明:本片文章在我的草稿箱已经尘封很久了,初稿时间是2014年9月8日,如下

 

     技术分享

 

     为什么我一直没有发出来呢? 是因为我的代码没有得到Yes,由于参加工作了,以后来研究的时间相对

     少点,现在发表出来希望有高手能指出错误之处,共同进步,谢谢!

 

 

 

以前写过表为平方和初级版,链接为http://blog.csdn.net/acdreamers/article/details/10083393

主要的问题是求形如技术分享丢番图方程的解。今天我将来探讨另一类丢番图方程的解,即技术分享

解。当然,我们需要先对技术分享素因子分解,得到形如技术分享的方程,其中技术分享为奇素数。根据技术分享的不同,方程有

解的条件也不一样。比如

 

(1)技术分享时,有解的条件是技术分享

(2)技术分享时,有解的条件是技术分享

 

接下来,我会重点以一道经典题目的解析来说明此类丢番图方程在竞赛中的应用。

 

题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3815

 

题意:给定两个正整数技术分享技术分享,其中技术分享技术分享,输出所有满足条件的三元组,并

     输出数据满足条件技术分享

 

分析:本题是2014年亚洲区域赛网络预选赛(牡丹江赛区)的G题。然而现场AC率为0,接下来进行详细探讨

 

     首先根据已知条件,我们可以得到如下

 

     技术分享

 

     再令技术分享,则有

 

      技术分享

 

     继续消去技术分享,得到

 

      技术分享

 

     令技术分享,得到技术分享,再将技术分享素因子分解,分别求出解,

     然后合并即可,合并的时候跟丢番图方程技术分享的合并类似,如下

 

      技术分享

 

     现在的关键问题是如何求解丢番图方程技术分享,其中技术分享为奇素数,此处技术分享

 

     那么有解的条件是技术分享,并且解唯一,求解技术分享技术分享的方法跟上次类似,具体步骤如下

 

     (1)先求出同余方程技术分享的最小正整数解技术分享

     (2)技术分享技术分享进行辗转相除运算,记录每次的余数为技术分享(注意第一次的余数为技术分享),当满足条件技术分享

         时停止,此时的技术分享就是技术分享技术分享可以通过技术分享得到,即

 

         技术分享

 

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <vector>
#include <math.h>
#include <set>
#include <map>

using namespace std;
const int N = 255;
const int M = 200005;
typedef long long LL;

char str[N];
LL a[N];

struct Pair
{
    LL x, y;
    bool operator < (const Pair &a) const
    {
        if(a.x == x) return a.y > y;
        return a.x > x;
    }
};
Pair node[M];

struct Res
{
    LL x, y, z;
    bool operator < (const Res &a) const
    {
        if(a.x == x && a.y == y) return a.z > z;
        if(a.x == x) return a.y > y;
        return a.x > x;
    }
};

set<Pair> Set;
set<Res> _Set;
set<Pair> Mem;
vector<LL> vec;

int sign[4][2] = {{-1, -1}, {-1, 1}, {1, -1}, {1, 1}};
int _sign[2][2] = {{-1, 1}, {1, -1}};

LL multi(LL a, LL b, LL m)
{
    LL ans = 0;
    a %= m;
    while(b)
    {
        if(b & 1)
        {
            ans = (ans + a) % m;
            b--;
        }
        b >>= 1;
        a = (a + a) % m;
    }
    return ans;
}

LL quick_mod(LL a, LL b, LL m)
{
    LL ans = 1;
    a %= m;
    while(b)
    {
        if(b & 1)
        {
            ans = multi(ans, a, m);
            b--;
        }
        b >>= 1;
        a = multi(a, a, m);
    }
    return ans;
}

struct T
{
    LL p, d;
};

LL w;

T multi_er(T a, T b, LL m)
{
    T ans;
    ans.p = (multi(a.p, b.p, m) + multi(multi(a.d, b.d, m), w, m)) % m;
    ans.d = (multi(a.p, b.d, m) + multi(a.d, b.p, m)) % m;
    return ans;
}

T power(T a, LL b, LL m)
{
    T ans;
    ans.p = 1;
    ans.d = 0;
    while(b)
    {
        if(b & 1)
        {
            ans = multi_er(ans, a, m);
            b--;
        }
        b >>= 1;
        a = multi_er(a, a, m);
    }
    return ans;
}

LL Legendre(LL a, LL p)
{
    return quick_mod(a, (p - 1) >> 1, p);
}

LL Work(LL n, LL p)
{
    if(p % 3 != 1) return -1;
    LL a = -1, t;
    while(1)
    {
        a = rand() % p;
        t = a * a - n;
        w = (t % p + p) % p;
        if(Legendre(w, p) + 1 == p) break;
    }
    T tmp;
    tmp.p = a;
    tmp.d = 1;
    T ans = power(tmp, (p + 1) >> 1, p);
    return ans.p;
}

LL Solve(LL n, LL p, LL &_x, LL &_y)
{
    LL x = Work(n, p);
    if(x == -1)
        return -1;
    if(x >= p - x)
        x = p - x;
    LL t = p;
    LL r = x;
    LL limit = (LL)sqrt(1.0 * p);
    while(r > limit)
    {
        x = r;
        r = t % x;
        t = x;
    }
    _x = r;
    _y = (LL)sqrt((p - r * r) / 3);
    return 0;
}

void Prepare(char str[], LL a[], int &cnt)
{
    cnt = 0;
    LL ans = 0;
    bool flag = 0;
    int len = strlen(str);
    for(int i=0; i<=len; i++)
    {
        if(str[i] >= '0' && str[i] <= '9')
            ans = ans * 10 + str[i] - '0';
        else if(str[i] == '-')
            flag = 1;
        else
        {
            if(flag) ans = -ans;
            a[cnt++] = ans;
            ans = 0;
            flag = 0;
        }
    }
}

bool getData(Pair node[], LL a[], int &cnt)
{
    int k = 0;
    int _cnt = 0;
    for(int i = 0; i < cnt; i++)
    {
        if(a[i] == 2) k++;
        if(k == 2)
        {
            node[_cnt].x = 1;
            node[_cnt].y = 1;
            _cnt++;
            k = 0;
        }
        if(a[i] > 2)
        {
            LL x, y;
            int ans = Solve(-3, a[i], x, y);
            if(ans == -1) return false;
            node[_cnt].x = x;
            node[_cnt].y = y;
            _cnt++;
        }
    }
    cnt = _cnt;
    if(k == 1) return false;
    return true;
}

void dfs(int dept, int cnt, Pair ans)
{
    if(dept == cnt - 1)
    {
        Set.insert(ans);
        return;
    }
    for(int i = 0; i < 4; i++)
    {
        for(int j = 0; j < 2; j++)
        {
            Pair _ans;
            _ans.x = ans.x * sign[i][0] * node[dept + 1].x + _sign[j][0] * 3 * ans.y * sign[i][1] * node[dept + 1].y;
            _ans.y = ans.x * sign[i][1] * node[dept + 1].y + _sign[j][1] * ans.y * sign[i][0] * node[dept + 1].x;
            if(Mem.find(_ans) != Mem.end()) return;
            Mem.insert(_ans);
            dfs(dept + 1, cnt, _ans);
        }
    }
}

void Merge(Pair node[], int cnt)
{
    Pair ans;
    for(int i = 0; i < 4; i++)
    {
        ans.x = sign[i][0] * node[0].x;
        ans.y = sign[i][1] * node[0].y;
        Mem.insert(ans);
        dfs(0, cnt, ans);
    }
}

void Filter(LL B)
{
    set<Pair>::iterator it;
    for(it = Set.begin(); it != Set.end(); it++)
    {
        LL a = it->x - it->y;
        if(a & 1) continue;
        a >>= 1;
        LL b = it->y;
        LL c = -a - b;
        LL _x = B + a - c;
        if(_x % 3) continue;
        _x /= 3;
        LL _y = _x - a;
        LL _z = _x + c;
        if(_x > _z) swap(_x, _z);
        if(_y > _z) swap(_y, _z);
        if(_x > _y) swap(_x, _y);
        Res res;
        res.x = _x;
        res.y = _y;
        res.z = _z;
        _Set.insert(res);
    }
    set<Res>::iterator _it;
    for(_it = _Set.begin(); _it != _Set.end(); _it++)
        printf("%lld %lld %lld\n", _it->x, _it->y, _it->z);
}

void Response(LL a[], int cnt)
{
    LL A = a[0];
    LL B = a[1];
    LL n = 3 * A - B * B;
    if(n == 0 && B % 3 == 0)
    {
        printf("%lld %lld %lld\n", B / 3, B / 3, B / 3);
        return;
    }
    if(n < 2) return;
    a += 2;
    cnt -= 2;
    sort(a, a + cnt);
    for(int i = 0; i < cnt; i++)
    {
        while(n % a[i] == 0)
        {
            vec.push_back(a[i]);
            n /= a[i];
        }
    }
    cnt = 0;
    vector<LL>::iterator it;
    for(it = vec.begin(); it != vec.end(); it++)
        a[cnt++] = *it;
    for(int i = cnt; i >= 1; i--)
        a[i] = a[i-1];
    a[0] = 2;
    cnt++;
    if(!getData(node, a, cnt)) return;
    Merge(node, cnt);
    Filter(B);
}

int main()
{
    int T;
    scanf("%d", &T);
    getchar();
    for(int t = 1; t <= T; t++)
    {
        vec.clear();
        Mem.clear();
        Set.clear();
        _Set.clear();
        int cnt;
        gets(str);
        Prepare(str, a, cnt);
        printf("Case #%d:\n", t);
        Response(a, cnt);
    }
    return 0;
}


 

最后附上鸟神的思路,虽然我不懂,但我感觉好厉害!!!

 

技术分享

技术分享

技术分享

 

 

 

 

 

表为平方和终极版

标签:

原文地址:http://blog.csdn.net/acdreamers/article/details/39125389

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!