2014新生暑假个人排位赛07

时间限制 1000 ms  内存限制 65536 KB

题目描述

现有正整数集A={i|i>0&&i<=n},求A的子集合B,使得对于任意x属于B,y属于B,x整除y或y整除x。优先考虑所含元素多的子集合,然后优先考虑所含元素和大的子集合,然后优先考虑字典序小的子集合。

输入格式

每组数据包含一行一个整数n(n<1e5).输入以EOF结束。

输出格式

每组数据输出一行,从小到大输出所求集合,注意行尾不要有空格。

输入样例

6
100

输出样例

1 3 6
1 3 6 12 24 48 96
输入N,求集合1<=x<=n,中的一个子集,使得子集中每两个元素可以互相被整除。要求输出子集,输出子集中元素个数多的,如果一样输出和最大的。


/*
USER_ID: test#wlwlxgg
PROBLEM: 443
SUBMISSION_TIME: 2014-07-28 14:57:26
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <vector>
#include <queue>
#include <map>
 
using namespace std;
 
int a[140000];
int b[19];
int c[17];
int d[140000];
int main()
{
    b[1]=2;
    for(int i=2;i<=17;i++)
        b[i]=2*b[i-1];
    c[1]=3;
    for(int i=2;i<=16;i++)
        c[i]=2*c[i-1];
    int m=1,n=1;
    for(int i=2;i<=100000;i++)
        if(i==b[m]){a[i]=1;m++;continue;}
        else if(i==c[n]){a[i]=0;n++;continue;}
        else a[i]=a[i-1];
    int t;
    while(~scanf("%d",&t)){
        if(t==1) puts("1");
        else if(t==2) printf("1 2\n");
        else if(t==3) printf("1 3\n");
        else if(a[t]==1){
            int k=0;
            printf("1 ");
            for(int i=2;i<=t;i*=2)
                d[k++]=i;
            for(int i=0;i<k;i++)
                if(i!=k-1)
                    printf("%d ",d[i]);
                else printf("%d\n",d[i]);
        }
        else {
            printf("1 ");
            int k=0;
            for(int i=3;i<=t;i*=2)
                d[k++]=i;
            for(int i=0;i<k;i++)
                if(i!=k-1)
                    printf("%d ",d[i]);
                else printf("%d\n",d[i]);
        }
    }
    ret


时间限制 1000 ms  内存限制 65536 KB

题目描述

有一个传说,对给定正整数 m 和 q,总有一个边长为 a,b,c 的三角形,是满足 a % m + b % m = c % m = q 的条件的三角形中周长最小的。
Mays 对此深信不疑,她打算和你一起探讨这个问题。她出了一些数据,请你帮忙求最小周长,如果找不到这样一个三角形,也请你告诉她这个惨痛的事实。

输入格式

给一个组数 T。接下来 T 组,每组两个数字 m 和 q ,(1 <= m <= 10^5 , 0 <= q < m)。

输出格式

输出当前组数和最小周长,格式见样例。若不存在满足的三角形,请把最小周长的数字替换成"Poor Mays!".

输入样例

2
3 2
3 2

输出样例

Case 1: 7
Case 2: 7
我是暴力做的。。。考虑了几种情况。


/*
USER_ID: test#wlwlxgg
PROBLEM: 453
SUBMISSION_TIME: 2014-07-28 16:29:29
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <vector>
#include <queue>
#include <map>
#define INF 1000000
using namespace std;
 
bool sanjiao(int a,int b,int c){
    if(a+b<=c||a+c<=b||b+c<=a)
        return false;
    return true;
}
 
int main()
{
    int t;
    scanf("%d",&t);
    for(int j=1;j<=t;j++){
        int m,q;
        int mint=INF;
        scanf("%d%d",&m,&q);
        if(q==0) printf("Case %d: %d\n",j,3*m);
        else {
            for(int i=0;i<q;i++)
                if(sanjiao(m+i,m+q-i,q))
                    mint=min(mint,m+i+m+q-i+q);
            for(int i=0;i<q;i++)
                if(sanjiao(m+i,q-i,q))
                    mint=min(mint,m+i+q-i+q);
            for(int i=0;i<q;i++)
                if(sanjiao(m+i,m+q-i,m+q))
                    mint=min(mint,m+i+m+q-i+m+q);
            for(int i=0;i<q;i++)
                if(sanjiao(m+i,q-i,m+q))
                    mint=min(mint,m+i+q-i+m+q);
            if(mint==INF)
                printf("Case %d: Poor Mays!\n",j);
            else printf("Case %d: %d\n",j,mint);
        }
    }
    return 0;
}


时间限制 5000 ms  内存限制 65536 KB

题目描述

小叮当刚刚学会了传送门的使用方法,可是它不小心跌落到二维空间一个 n * m 的矩阵格子世界的入口(1,1)处,
他得知出口在(n,m)处,每穿越一个格子门,它的体力值会下降。
又饿又累的他 IQ 已经降为负数了,聪明的你,能帮他规划一下路线,使得它体力值下降的最少吗?
每一行有且仅有一个传送门,但是小叮当上课睡着了,只学会了用传送门瞬移到相邻行的另一个传送门且耗 1 滴体力。
此外,他就只能通过格子门走到相邻四个格子中的一个,也耗 1 滴体力。
ps,由于符合的路径太多了,你只需要告诉我们体力值消耗最小值。

 

输入格式

每组数据,第一行给 n,m 两个整数(2 <= n,m <= 10000),接下来一行,有 n 个数字,代表该行传送门的位置 x( 1 <= x <= m )。以 n,m 都为0结束。Mays温馨提醒:数据组数略大于100。

输出格式

对每组输入,输出一行,体力消耗最小值。

输入样例

5 5
5 4 3 2 1
0 0

输出样例

8
比赛的时候感觉贪心是对的,就没有多想,结果就错了。其实是一个spfa。


/*
USER_ID: test#wlwlxgg
PROBLEM: 454
SUBMISSION_TIME: 2014-07-31 23:39:49
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <vector>
#include <queue>
#include <map>
#define MAXV 10010
#define MAXE 40040
#define INF 100000000
 
using namespace std;
 
int n,m;
struct{int to,next,cost;}e[MAXE];
int head[MAXV],cnt;
int vis[MAXV],d[MAXV];
 
void add(int u,int v,int cost){
    e[cnt].to=v;
    e[cnt].next=head[u];
    e[cnt].cost=cost;
    head[u]=cnt++;
}
 
void SPFA(int s){
    for(int i=0;i<=n+10;i++){
        d[i]=INF;
        vis[i]=0;
    }
    queue<int>q;
    d[s]=0;
    vis[s]=1;
    q.push(s);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int i=head[u];i;i=e[i].next){
            if(d[e[i].to]>d[u]+e[i].cost){
                d[e[i].to]=d[u]+e[i].cost;
                if(!vis[e[i].to])
                    vis[e[i].to]=1;
                    q.push(e[i].to);
            }
        }
        vis[u]=0;
    }
 
}
 
int main()
{
    while(~scanf("%d%d",&n,&m)){
        if(m==0&&n==0)break;
        memset(head,0,sizeof(head));
        cnt=1;
        for(int i=2;i<=n+1;i++){
            int x;
            scanf("%d",&x);
            add(1,i,x+i-3);
            add(i,n+2,m+n-x-i+1);
        }
        for(int i=2;i<=n;i++){
            add(i,i+1,1);
            add(n-i+3,n-i+2,1);
        }
        SPFA(1);
        printf("%d\n",d[n+2]);
    }
    return 0;
}


时间限制 2000 ms  内存限制 65536 KB

题目描述

小弱最近在研究质数,他认为两个数互质是一个好性质。现在hiyot大神为了考考他学习的成果,给了他长度为n的整数序列a1、a2 .. an。同时给了他下面了两种操作:
操作一:"1 l r", 先求出区间[l, r]的所有数的gcd, 再计算[2,m]中有多少个数与gcd互质。
操作二: "2 p x", 把a[p]数值替换为x( 1 <= x <= 1000)
小弱是弱渣,但是如果你做出来了,他会认可你为大神,请你帮他算算。

输入格式

有多组数据。
每组数据以n( 1<=n<=10000), m(2<=m<=1000000), q(1<=q<=10000)开头。接下来一行有n(1 <= ai <= 1000)个数。最后q行每行有三个数,对应于一个操作。

输出格式

对每一个查询输出对应个数(如果区间gcd为1,则输出-1)。

输入样例

5 10 10
2 2 3 3 5
1 1 4
1 3 3
1 5 5
1 1 2
2 3 2
2 4 2
1 1 4
2 3 10
2 4 10
1 3 4

输出样例

-1
6 
7
4
4
3

用线段树,求gcd就不用说了,后面再用容斥去算出2-m的个数。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#define MAX_N 40000
#define ll long long
using namespace std;

int array_gcd[MAX_N<<2];
int n,m,q;

int gcd(int a,int b){
    return b == 0 ? a : gcd(b,a%b);
}

void PushUP(int rt){
    array_gcd[rt]=gcd(array_gcd[rt<<1],array_gcd[rt<<1|1]);
}

void build(int l,int r,int rt){
    if(l==r){
        scanf("%d",&array_gcd[rt]);
        return ;
    }
    int m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    PushUP(rt);
}

void updata(int p,int sc,int l,int r,int rt){
    if(l==r){
        array_gcd[rt]=sc;
        return ;
    }
    int m=(l+r)>>1;
    if(p<=m) updata(p,sc,l,m,rt<<1);
    else updata(p,sc,m+1,r,rt<<1|1);
    PushUP(rt);
}

int query(int L,int R,int l,int r,int rt){
    if(L<=l&&r<=R)
        return array_gcd[rt];
    int m=(l+r)>>1;
    int ret=0;
    if(L<=m) ret=gcd(ret,query(L,R,l,m,rt<<1));
    if(R>m) ret=gcd(ret,query(L,R,m+1,r,rt<<1|1));
    return ret;
}

int rongchi(int l,int r){
    int num=0;
    int prime[10000];
    int x=query(l,r,1,n,1);
    for(int i=2;i*i<=x;i++){
        if(x&&x%i==0){
            prime[num++]=i;
            while(x&&x%i==0)
                x/=i;
        }
    }
    if(x>1) prime[num++]=x;

    ll temp,flag,ans=0;
    for(int i=1;i<(ll)(1<<num);i++){
        temp=1,flag=0;
        for(int j=0;j<num;j++)
            if(i&(ll)(1<<j))
                flag++,temp*=prime[j];
        if(flag&1)
            ans+=m/temp;
        else
            ans-=m/temp;
    }
    return m-1-ans;
}

int main()
{
    while(~scanf("%d%d%d",&n,&m,&q)){
        build(1,n,1);
        int modern;
        for(int i=0;i<q;i++){
            scanf("%d",&modern);
            if(modern==1){
                int l,r;
                scanf("%d%d",&l,&r);
                if(query(l,r,1,n,1)==1) puts("-1");
                else printf("%d\n",rongchi(l,r));
            }
            else {
                int p,x;
                scanf("%d%d",&p,&x);
                updata(p,x,1,n,1);
            }
        }
    }
    return 0;
}









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值