2017 清北济南考前刷题Day 1 morning

期望得分:100+100+50=250

实际得分:100+60+50=210

T2 二分 估错上界、估错复杂度

T1 立方数(cubic)

Time Limit:1000ms   Memory Limit:128MB

题目描述

LYK定义了一个数叫“立方数”,若一个数可以被写作是一个正整数的3次方,则这个数就是立方数,例如1,8,27就是最小的3个立方数。

现在给定一个数P,LYK想要知道这个数是不是立方数。

当然你有可能随机输出一些莫名其妙的东西来骗分,因此LYK有T次询问~

输入格式(cubic.in)

第一行一个数T,表示有T组数据。

接下来T行,每行一个数P。

输出格式(cubic.out)

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

输入样例

3

8

27

28

输出样例

YES

YES

NO

数据范围

对于30%的数据p<=100。

对于60%的数据p<=10^6。

对于100%的数据p<=10^18,T<=100。

预处理所有立方数,hash

//#include<set>
#include<cstdio>
#include<iostream>

using namespace std;

typedef long long LL;

//#define mod1 9000011
#define mod 3000017

//set<LL>s;
LL has[mod+3];

int bit[21];

void read(LL &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-‘0‘; c=getchar(); }
}

void insert(LL x)
{
    LL t=x; int len=0,now=0;
    while(t)
    {
        now+=t%10*bit[len++];
        while(now>=mod) now-=mod;
        t/=10;
    }

    while(has[now])
    {
        now++;
        if(now==mod) now=0;
    }
    has[now]=x;
}

bool find(LL x)
{
    LL t=x; int len=0,now=0;
    while(t)
    {
        now+=t%10*bit[len++];
        while(now>=mod) now-=mod;
        t/=10;
    }
    while(has[now])
    {
        if(has[now]==x) return true;
        now++; if(now==mod) now=0;
    }
    return false;
}

int main()
{
    freopen("cubic.in","r",stdin);
    freopen("cubic.out","w",stdout);
    bit[0]=1;
    for(int i=1;i<=20;i++) bit[i]=37*bit[i-1]%mod;
    for(int i=1;i<=1000000;i++)//    s.insert(1LL*i*i*i);
        insert(1LL*i*i*i);
    int T;
    scanf("%d",&T);
    LL x;
    while(T--)
    {
        read(x);
        //puts(s.find(x)!=s.end() ? "TES" : "NO" );
        puts(find(x) ? "YES" : "NO");
    }
}

T2 立方数2(cubicp)

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是个质数!

输入格式(cubicp.in)

第一行一个数T,表示有T组数据。

接下来T行,每行一个数P。

输出格式(cubicp.out)

输出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。

p = a^3 - b^3 = (a-b) (a^2 +ab +b^2)

因为p为素数,所以 一定是 (a-b)=1

a=b+1

后面的式子用b+1 替换 a

转化为 3*b^2 + 3*b + 1

枚举 b 即可

#include<cstdio>

using namespace std;

int main()
{
    freopen("cubicp.in","r",stdin);
    freopen("cubicp.out","w",stdout);
    int T;
    scanf("%d",&T);
    long long p,t;
    while(T--)
    {
        scanf("%I64d",&p);
        for(int i=1;;++i)
        {
            t= 1LL*3*i*i + 3*i + 1 ;
            if(t==p) { puts("YES"); break; }
            if(t>p) { puts("NO"); break; }
        }
    }
}

猜数字(number)

Time Limit:1000ms   Memory Limit:128MB

题目描述

LYK在玩猜数字游戏。

总共有n个互不相同的正整数,LYK每次猜一段区间的最小值。形如[li,ri]这段区间的数字的最小值一定等于xi。

我们总能构造出一种方案使得LYK满意。直到…… LYK自己猜的就是矛盾的!

例如LYK猜[1,3]的最小值是2,[1,4]的最小值是3,这显然就是矛盾的。

你需要告诉LYK,它第几次猜数字开始就已经矛盾了。

输入格式(number.in)

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

输出格式(number.out)

输出一个数表示第几次开始出现矛盾,如果一直没出现矛盾输出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的)。

如果一个小数的区间被一个大数的区间完全覆盖

那么就发生了矛盾

二分答案

将二分范围内的区间 按猜的数 从大到小 排序

并查集维护一个位置之后第一个没有被覆盖的位置,以此判断区间是否被完全覆盖

注意 正整数互不相同

所以若猜的同一个数 有 多个互不相交的区间,也是有矛盾的

判断这个就是 左端点的最大值>右端点的最小值

#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;

int n;

#define N 1000001

struct node
{
    int l,r,x;
}e[N],g[N];

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-‘0‘; c=getchar(); }
}

bool cmp(node p,node q)
{
    return p.x>q.x;
}

int fa[N+1];

int find(int i) { return fa[i]==i ? i : fa[i]=find(fa[i]); }

bool check(int k)
{
    for(int i=1;i<=k;++i) g[i]=e[i];
    sort(g+1,g+k+1,cmp);
    int lmin=g[1].l,rmin=g[1].r,lmax=g[1].l,rmax=g[1].r;
    for(int i=1;i<=n+1;++i) fa[i]=i;
    for(int i=2;i<=k;++i)
    {
        if(g[i].x<g[i-1].x)
        {
            if(find(lmax)>rmin) return false;
            for(int j=find(lmin);j<=rmax;++j) fa[find(j)]=find(rmax+1);
            lmin=lmax=g[i].l;
            rmin=rmax=g[i].r;
        }
        else
        {
            lmin=min(lmin,g[i].l);
            lmax=max(lmax,g[i].l);
            rmin=min(rmin,g[i].r);
            rmax=max(rmax,g[i].r);
            if(lmax>rmin) return false;
        }
    }
    if(find(lmax)>rmin) return false;
    return true;
}

int main()
{
    freopen("number.in","r",stdin);
    freopen("number.out","w",stdout);
    int T;
    read(n); read(T);
    for(int i=1;i<=T;++i) read(e[i].l),read(e[i].r),read(e[i].x);
    int l=1,r=T,mid,ans=T+1;
    while(l<=r)
    {
        mid=l+r>>1;
        if(!check(mid)) ans=mid,r=mid-1;
        else l=mid+1;
    }
    cout<<ans;
}

#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;

int n;

#define N 1000001

struct node
{
    int l,r,x;
}e[N],g[N];

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-‘0‘; c=getchar(); }
}

bool cmp(node p,node q)
{
    return p.x>q.x;
}

int fa[N+1];

int find(int i) { return fa[i]==i ? i : fa[i]=find(fa[i]); }

bool check(int k)
{
    for(int i=1;i<=k;++i) g[i]=e[i];
    sort(g+1,g+k+1,cmp);
    int lmin=g[1].l,rmin=g[1].r,lmax=g[1].l,rmax=g[1].r;
    for(int i=1;i<=n+1;++i) fa[i]=i;
    for(int i=2;i<=k;++i)
    {
        if(g[i].x<g[i-1].x)
        {
            if(find(lmax)>rmin) return false;
            for(int j=find(lmin);j<=rmax;++j) fa[find(j)]=find(rmax+1);
            lmin=lmax=g[i].l;
            rmin=rmax=g[i].r;
        }
        else
        {
            lmin=min(lmin,g[i].l);
            lmax=max(lmax,g[i].l);
            rmin=min(rmin,g[i].r);
            rmax=max(rmax,g[i].r);
            if(lmax>rmin) return false;
        }
    }
    if(find(lmax)>rmin) return false;
    return true;
}

int main()
{
    freopen("number.in","r",stdin);
    freopen("number.out","w",stdout);
    int T;
    read(n); read(T);
    for(int i=1;i<=T;++i) read(e[i].l),read(e[i].r),read(e[i].x);
    int l=1,r=T,mid,ans=T+1;
    while(l<=r)
    {
        mid=l+r>>1;
        if(!check(mid)) ans=mid,r=mid-1;
        else l=mid+1;
    }
    cout<<ans;
}

时间: 2024-10-13 09:50:02

2017 清北济南考前刷题Day 1 morning的相关文章

2017 清北济南考前刷题Day 5 afternoon

期望得分:100+100+30=230 实际得分:0+0+0=30 T1 直接模拟 #include<cstdio> #include<iostream> using namespace std; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } #define N 1002

2017 清北济南考前刷题Day 5 morning

期望得分:100+100+0=200 实际得分: 坐标的每一位不是0就是1,所以答案就是 C(n,k) #include<cstdio> #include<iostream> using namespace std; const int mod=1e9+7; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0';

2017 清北济南考前刷题Day 3 morning

实际得分:100+0+0=100 T1 右上角是必败态,然后推下去 发现同行全是必胜态或全是必败态,不同行必胜必败交叉 列同行 所以n,m 只要有一个是偶数,先手必胜 #include<cstdio> using namespace std; int main() { freopen("star.in","r",stdin); freopen("star.out","w",stdout); int n,m; whi

2017 清北济南考前刷题Day 2 morning

期望得分:100+30+60=190 实际得分:100+30+30=160 T1 最优方案跳的高度一定是单调的 所以先按高度排序 dp[i][j] 跳了i次跳到j 枚举从哪儿跳到j转移即可 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define N 51 struct node { int c,h; }e[N]

清北考前刷题day7早安

清北考前刷题da7下午好

三向城 /* 原图一定是一棵完全二叉树. 根节点是x,左节点是x*2,右节点是x*2+1 转化为二进制往左右走就很明显了. */ #include<iostream> #include<cstdio> #include<cstring> #define ll long long using namespace std; int T,x,y,k,ans,pos; inline int read() { int x=0,f=1;char c=getchar(); while

清北考前刷题day6下午好

/* 贪心 负数一定不取 枚举最高位是1 且答案取为0的 位置, 更新答案. */ #include<iostream> #include<cstdio> #include<cstring> #define ll long long #define N 100010 using namespace std; int n; ll a[N],ans,sum[N]; char s[N]; ll read() { ll x=0,f=1;char c=getchar(); whi

2017清北精英班整理内容掌握考试题

精英班考试题 2017.2.10 题目名 工资 藏妹子之处 银河之星 源文件 money.cpp/c/pas excel.pas/cpp galaxy.cpp/c/pas 输入文件 money.in excel.in galaxy.in 输出文件 money.out excel.out galaxy.out 时间限制 1000MS 1000MS 1000MS 内存限制 256MB 128MB 256MB 测试点 10 10 10 测试点分值 10 10 10 第一题 工资 链接 第二题  藏妹子

2017清北学堂集训笔记——图论

我们进入一个新的模块——图论! emmmmm这个专题更出来可能有点慢别介意,原因是要划的图和要给代码加的注释比较多,更重要的就是...这几个晚上我在追剧!!我们的少年时代超级超级超级好看,剧情很燃啊!!咳咳,好吧下面回归正题. 一.图的存储: 1.邻接矩阵: 假设有n个节点,建立一个n×n的矩阵,第i号节点能到达第j号节点就将[i][j]标记为1(有权值标记为权值), 样例如下图: 1 /*无向图,无权值*/ 2 int a[MAXN][MAXN];//邻接矩阵 3 int x,y;//两座城市