2017.11.1清北测试

Problem 1 :立方数

Time Limit:1000ms Memory Limit:128MB

题目描述

LYK定义了一个数叫“立方数”,若一个数可以被写作是一个正整数的3次方,则这个数就是立方数,例如1,8,27就是最小的3个立方数。
现在给定一个数P,LYK想要知道这个数是不是立方数。
当然你有可能随机输出一些莫名其妙的东西来骗分,因此LYK有T次询问~

输入格式
第一行一个数T,表示有T组数据。
接下来T行,每行一个数P。

输出格式
输出T行,对于每个数如果是立方数,输出“YES”,否则输出“NO”。

输入样例
3
8
27
28

输出样例
YES
YES
NO

数据范围
对于30%的数据p<=100。
对于60%的数据p<=10^6。
对于100%的数据p<=10^18,T<=100。

思路
暴力枚举1-10^6范围内的数,求其三次方与p比较看是否存在一次相等的情况。
考场只注意最后结果不要炸int…..却十分愚蠢的忽略了求三次方过程中也会炸
三个int相乘结果赋给unsigned long long的过程中好像还要将结果用int储存一下再赋值….白白丢失了30分。
1-10^6内的数显然是单增的,也可以二分查找与p相等的立方差数。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define RI register int
using namespace std;
int t;
bool flag;
unsigned long long p,x;
int main()
{
    scanf("%d",&t);
    for(RI i=1;i<=t;i++)
    {
        flag=0;
        scanf("%llu",&p);
        for(unsigned long long j=1;j<=1000000;j++)//戒之慎勿忘
        {
            x=j*j*j;//1-10^18立方数 
            if(p==x)
            {
                flag=1;
                break;
            }
            if(x>p)
            break;//没有与p相等的数
        }
        if(flag)
        printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

Problem 1 :立方数2

Time Limit:1000ms Memory Limit:128MB

题目描述

LYK定义了一个数叫“立方数”,若一个数可以被写作是一个正整数的3次方,则这个数就是立方数,例如1,8,27就是最小的3个立方数。
LYK还定义了一个数叫“立方差数”,若一个数可以被写作是两个立方数的差,则这个数就是“立方差数”,例如7(8-1),26(27-1),19(27-8)都是立方差数。
现在给定一个数P,LYK想要知道这个数是不是立方差数。
当然你有可能随机输出一些莫名其妙的东西,因此LYK有T次询问~
这个问题可能太难了…… 因此LYK规定P是个质数

输入格式
第一行一个数T,表示有T组数据。
接下来T行,每行一个数P。

输出格式
输出T行,对于每个数如果是立方差数,输出“YES”,否则输出“NO”。

输入样例
5
2
3
5
7
11

输出样例
NO
NO
NO
YES
NO

数据范围
对于30%的数据p<=100。
对于60%的数据p<=10^6。
对于100%的数据p<=10^12,T<=100。

正解思路
立方差公式
a³ - b³ = (a - b)(a² + ab + b²) = p
因为p为质数,那么可得(a - b) = 1,(a² + ab + b²) = p或(a² + ab + b²) = 1,(a - b) = 1。
因为a,b都为大于0的正整数显然(a² + ab + b²)是不可能 = 1的,则(a - b) = 1,(a² + ab + b²) = p。
那么a = b + 1,将此结论带入(a² + ab + b²) = p中得:
3b² + 3b + 1 = p。
那么b一定是小于根号p的,枚举1-10^6范围内的数看计算是否与p相同。—思路1
——————————————————————————————
或者,我们再得到b = a - 1这个结论后
我们通过计算器计算得到——575001^3 - 575000^3为一个的大于10^12的两个数的差值。(显然这个结论也是可以应用于我们的上文中的思路的)那么也就是说,对于p<=10^12,我们只需要枚举1-575000范围内的a,b = a–1,求其三次方数作差看是否与p相同。—思路2

考场思路
惊人地没想到立方差…而想到了完全立方公式…:
a³ - b³ = (b + c)³ - b³ = b³ + 3b²c + 3bc² + c³ - b³ = 3b²c + 3bc² + c³…. = p
b一定是小于根号p的,c一定是小于三次根号p的….那么我们枚举b…和c…
只有60分…

考场代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define RI register int
using namespace std;
int t;
bool flag;
bool ban[30000010];
unsigned long long p,x;
int main()
{
    scanf("%d",&t);
    for(int i=1;i<=t;i++)//p+(b+c)^3=a^3
    {
        scanf("%llu",&p);
        flag=0;
        for(RI i=1;i<=1000;i++)//枚举b,b^2<p 
        {
            for(RI j=1;j<=100;j++)//枚举c,c^3<p 
            {
                x=3*i*i*j+3*i*j*j+j*j*j;//x+(b+c)^3=b^3,必定为立方数 
                if(p==x)
                {
                    flag=1;
                    break;
                }
            }
            if(flag)
            break;
        }
        if(flag)
        printf("YES\n");
        else printf("NO\n"); 
    }
    return 0;
}

正解代码

思路1

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define RI register int
using namespace std;
int t;
bool flag;
bool ban[30000010];
unsigned long long p,x;
int main()
{
    scanf("%d",&t);
    for(int i=1;i<=t;i++)
    {
        scanf("%llu",&p);
        flag=0;
        for(unsigned long long i=1;i<=575000;i++)
        //575001^3-575000^3是第一个大于10^12的差值
        {
            x=3*i*i+3*i+1;
            if(p==x)
            {
                flag=1;
                break;
            }
            if(x>p)
            break;
        }
        if(flag)
        printf("YES\n");
        else printf("NO\n"); 
    }
    return 0;
}

思路2

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define RI register int
using namespace std;
int t;
bool flag;
bool ban[30000010];
unsigned long long p,x,y;
int main()
{
    scanf("%d",&t);
    for(int i=1;i<=t;i++)
    {
        scanf("%llu",&p);
        flag=0;
        for(unsigned long long i=1;i<=575000;i++)
        {
            x=i*i*i;
            y=(i-1)*(i-1)*(i-1);
            if(p==(x-y))
            {
                flag=1;
                break;
            }
            if((x-y)>p)
            break;
        }
        if(flag)
        printf("YES\n");
        else printf("NO\n"); 
    }
    return 0;
}

Problem 1 :猜数字

Time Limit:2000ms Memory Limit:128MB

题目描述

LYK在玩猜数字游戏。
总共有n个互不相同的正整数,LYK每次猜一段区间的最小值。形如[li,ri]这段区间的数字的最小值一定等于xi。
我们总能构造出一种方案使得LYK满意。直到…… LYK自己猜的就是矛盾的!
例如LYK猜[1,3]的最小值是2,[1,4]的最小值是3,这显然就是矛盾的。
你需要告诉LYK,它第几次猜数字开始就已经矛盾了。

输入格式
第一行两个数n和T,表示有n个数字,LYK猜了T次。
接下来T行,每行三个数分别表示li,ri和xi。

输出格式
输出一个数表示第几次开始出现矛盾,如果一直没出现矛盾输出T+1。

输入样例
20 4
1 10 7
5 19 7
3 12 8
1 20 1

输出样例
3

数据范围
对于50%的数据n<=8,T<=10。
对于80%的数据n<=1000,T<=1000。
对于100%的数据1<=n,T<=1000000,1<=li<=ri<=n,1<=xi<=n(但并不保证一开始的所有数都是1~n的)。

Hint
建议使用读入优化

思路
显然,若按照题目给定的顺序处理,判断过程将异常麻烦….数据水的情况忽略
但仔细分析题目后发现,本题对矛盾的产生有着诸多限制在。
那么我们可以考虑,对于矛盾的情况下一个统一定义
对于本题,则为“若某一确定了最小值的区间,被一个或多个最小值比他大的区间完全覆盖,那么此时的情况就是矛盾的。”—— 注意适当的将此种方法扩展到其他题目,使给定信息变得规律而易于处理。
由此我们就可以二分产生矛盾的第一个位置,将该位置及以前的猜测条件按猜测最小值从大到小排序后依次判断验证,因为顺序并不会影响矛盾的产生。
如何判断呢?
暴力枚举之前的猜测——80分!
线段树或并查集——正解。

实现方法可以参考Codevs1191数轴染色理解…
http://blog.youkuaiyun.com/qq_36693533/article/details/78428668

正解传送门:
http://blog.youkuaiyun.com/qq_36693533/article/details/78441146

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值