ZOJ3673:1729

1729 is the natural number following 1728 and preceding 1730. It is also known as the Hardy-Ramanujan number after a famous anecdote of the British mathematician G. H. Hardy regarding
a hospital visit to the Indian mathematician Srinivasa Ramanujan. In Hardy‘s words:

I remember once going to see him when he was ill at Putney. I had ridden in taxi cab number 1729 and remarked that the number seemed to me rather a dull one, and that I hoped it was not an unfavorable omen. "No," he replied, "it is a very interesting
number; it is the smallest number expressible as the sum of two (positive) cubes in two different ways."

The two different ways are these: 1729 = 13 + 123 = 93 + 103

Now your task is to count how many ways a positive number can be expressible as the sum of two positive cubes in. All the numbers in this task can be expressible as the sum of two positive cubes in at least one way.

Input

There‘re nearly 20,000 cases. Each case is a positive integer in a single line. And all these numbers are greater than 1 and less than 264.

Output

Please refer to the sample output. For each case, you should output a line. First the number of ways n. Then followed by n pairs of integer, (ai,bi),
indicating a way the given number can be expressible as the sum of ai‘s cube and bi‘s. (ai≤ bi, and a1a2<
...< an)

Sample Input

9
4104
2622104000
21131226514944
48988659276962496

Sample Output

1 (1,2)
2 (2,16) (9,15)
3 (600,1340) (678,1322) (1020,1160)
4 (1539,27645) (8664,27360) (11772,26916) (17176,25232)
5 (38787,365757) (107839,362753) (205292,342952) (221424,336588) (231518,331954)

Hint

Although most numbers cannot be expressible as the sum of two positive cubes, the vast majority of numbers in this task can be expressible as the sum of two positive cubes in two or more ways.

题意比较简单,就不解释了

这题还真是弄了好久,再加上犯的各种小错误,但是终于算是搞出来了,不容易啊。。。

思路:要求满足的m=a3+b3=(a+b)(a2-ab+b2)的(a,b)组合。

令t=a+b,则t一定是m的约数,所以应枚举m的所有约数。

然后可以得到

a+b=t

ab=(t2-m/t)/3=p

继而转化为a2-ta+p=0是否有正整数解就可以了。

再就是注意范围要用unsigned long long。

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
using namespace std;
#define ll unsigned long long
#define maxn 2642246//2^64次方的开立方
#define L 5000001
ll n;
ll prime[L],divi[500],e[500];
int len,len_prime,len_s;
bool flag[L] = {false};
struct node
{
    ll x,y;
} s[1005];

int cmp(node x,node y)
{
    return x.x<y.x;
}

void init()//素数且不说,所有合数都能分解成任意素数之积
{
    int i,j;
    len_prime = 0;
    for(i = 2; i<L; i++)
    {
        if(!flag[i]) prime[len_prime++] = i;//打下素数表
        for(int j = 0; j<len_prime && i*prime[j]<L; j++)
        {
            flag[i*prime[j]] = true;//所有非素数排除
            if(i%prime[j]==0) break;
        }
    }
}

void find_div(ll m)//找出m的所有素因子
{
    int i;
    ll k;
    len = 0;
    for(i = 0; i<len_prime && prime[i]*prime[i]<=m; i++)
    {
        if(m%prime[i] == 0)
        {
            divi[len] = prime[i];//因子保存
            k = 1;
            m/=prime[i];
            while(m%prime[i] == 0)//除尽为止
            {
                k++;//记录个数
                m/=prime[i];
            }
            e[len++] = k;
        }
    }
    if(m>1)
    {
        divi[len] = m;
        e[len++] = 1;
    }
}

ll can_sqrt(ll c)//要求整数解,b^2-4*a*c必须能开出整数
{
    ll r = sqrt(1.0*c);
    if(r*r == c) return r;
    return L;
}

int judge(ll x,ll y)//看这组解是否已经存在
{
    for(int i=0; i<len_s; i++)
        if(s[i].x==x&&s[i].y==y)
            return 1;
    return 0;
}

void solve(ll t)//找出解
{
    ll x1,x2;
    ll k = n/t;
    ll r = t*t-k;
    if(r>0 && r%3!=0) return ;
    r/=3;
    ll dis = t*t-4*r;
    if(dis<0) return ;
    ll c = can_sqrt(dis);
    if(c == L) return;
    if((t+c)%2 == 0)
    {
        x1 = (t+c)/2;
        x2 = t-x1;
        if(x1>x2) swap(x1,x2);
        if(x1>0&&x1<t&&x1<maxn&&x2<maxn&&x2>0&&x2<t&&!judge(x1,x2))
        {
            s[len_s].x=x1;
            s[len_s++].y=x2;
        }
    }
    if((t-c)>0 && (t-c)%2 == 0)
    {
        x1 = (t-c)/2;
        x2 = t-x1;
        if(x1>x2) swap(x1,x2);
        if(x1>0&&x1<t&&x1<maxn&&x2<maxn&&x2>0&&x2<t&&!judge(x1,x2))
        {
            s[len_s].x=x1;
            s[len_s++].y=x2;
        }
    }
}

ll ppow(ll a,ll b)
{
    ll ans = 1;
    while(b)
    {
        if(b&1) ans*=a;
        b>>=1;
        a*=a;
    }
    return ans;
}

void dfs(int m,ll sum)
{
    solve(sum);
    if(m>=len) return ;
    for(int i = 0; i<=e[m]; i++)//由个数去枚举次方,1为a,2为a^2,3为a^3,如此类推,枚举所有t
        dfs(m+1,sum*ppow(divi[m],i));
}

int main()
{
    init();
    while(~scanf("%llu",&n))
    {
        find_div(n);
        len_s = 0;
        dfs(0,1);
        sort(s,s+len_s,cmp);
        printf("%d",len_s);
        for(int i = 0; i<len_s; i++)
            printf(" (%llu,%llu)",s[i].x,s[i].y);
        printf("\n");
    }

    return 0;
}

ZOJ3673:1729,布布扣,bubuko.com

时间: 2024-10-06 05:24:25

ZOJ3673:1729的相关文章

3223: Tyvj 1729 文艺平衡树

3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3473  Solved: 1962[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 Input 第一行为n,m n表示初始序列有n个数,这个序列依次

BZOJ 3223: Tyvj 1729 文艺平衡树

3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3629  Solved: 2053[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 Input 第一行为n,m n表示初始序列有n个数,这个序列依次

poj 1729 Jack and Jill (搜索,bfs)

原题网址:http://bailian.openjudge.cn/practice/1729 思路: 用点对表示两个人的状态,放在队列中(队列也可以用优先队列),当到达一个点对的路径上的最近距离大于先前求得的最近距离则进行更新. 注意:可能两人的最近距离是0,在更新的时候要注意. 详细代码: 普通队列: 1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <algorithm

[HZOI 2016][Tyvj 1729]文艺平衡树 这道题我真是哭了,调了一下午,一晚上

[题目描述] 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 [输入格式] 第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2--n-1,n)  m表示翻转操作次数 接下来m行每行两个数[l,r] 数据保证 1<=l<=r<=n [输出格式] 输出一行n个数字,表示原始序列经过m次变换后的结果 [样例输入] 5 3 1 3 1 3 1 4 [

BZOJ3223: Tyvj 1729 文艺平衡树 [splay]

3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3595  Solved: 2029[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 Input 第一行为n,m n表示初始序列有n个数,这个序列依次

bzoj 3223/tyvj 1729 文艺平衡树 splay tree

原题链接:http://www.tyvj.cn/p/1729 这道题以前用c语言写的splay tree水过了.. 现在接触了c++重写一遍... 只涉及区间翻转,由于没有删除操作故不带垃圾回收,具体如下: 1 #include<cstdio> 2 #include<cstdlib> 3 #include<iostream> 4 #include<algorithm> 5 const int MAX_N = 100010; 6 struct Node{ 7

hdu 1729 Stone Game SG函数

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1729 题意:2个玩家,有N个箱子,每个箱子的大小是Si,游戏开始前,就有一些石子在这些箱子里了. 游戏者轮流选择箱子,然后把石子放入箱子里.并且放入的石子数量不能大于原来箱子里就有的石子的数量的平方. 比如说,一个箱子里已经有了3个石头,则可以放1-9个石头(小于箱子的容量). 当轮到某人时,不能再放石子则为输. 问能否找到一种策略使先手必赢. 学习了一下SG函数. 在公平的组合游戏中(游戏规则对于

【vijos】1729 Knights(匈牙利)

https://vijos.org/p/1729 这题好奇葩,为嘛N开到30就会re啊..........n<=26吗.... sad 因为根据棋子的分布,能攻击的一定各在一黑白格上,所以直接二分图了. (但是我想了想,如果不是黑白格的,怎么做............................ #include <cstdio> #include <cstring> #include <cmath> #include <string> #incl

bzoj3223Tyvj 1729 文艺平衡树

bzoj3223Tyvj 1729 文艺平衡树 题意: 一个数列,支持区间翻转操作. 题解: splay裸题.注意涉及到区间操作的一般用splay不用treap. 代码: 1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #define inc(i,j,k) for(int i=j;i<=k;i++) 5 #define fa(x) nds[x].fa 6 #define ch(x,