[Contests]2016 ACM/ICPC Asia Regional Qingdao Online(1001/2/4/5/6)

1001 I Count Two Three

题意:

给你一个数n(1<=n<=1e9),让你求一个数re,re满足re= 2a3b5c7d  && re>=n

思路:

打表+二分

代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
/*
打表+二分
*/
const int N = 500000+5;
int tab[N];
int n=0, num;
__int64 my_pow(int x, int num){
    __int64 sum=1;
    while(num>0){
        sum *= x;
        num--;
    }
    return sum;
}
//打表
void table(){
    int i,j,k,w;
    __int64 tmp=0;
    for(i=0; i<=30; i++)
    for(j=0; j<=19; j++)
    for(k=0; k<=13; k++)
    for(w=0; w<=11; w++){
        tmp = my_pow(2,i) * my_pow(3,j);
        if(tmp>1e9) break;
        tmp *= my_pow(5,k);
        if(tmp>1e9) break;
        tmp *= my_pow(7,w);
        if(tmp>1e9) break;
        tab[n++] = tmp;
    }
    sort(tab,tab+n);
}
int main(){
    int t;
    table();//5174个
    scanf("%d", &t);
    while(t-->0){
        scanf("%d", &num);
        int x = lower_bound(tab,tab+n,num)-tab;
        printf("%d\n", tab[x]);
    }
    return 0;
}


1002 Cure

题意:

给你一个数n,让你求1/k^2(1<=k<=n)的和,但是没给n的具体范围,给了这个“The input file is at most 1M.”也不懂啥意思……

思路:

一开始直接记忆化搜索,然后理所当然的TLE了_(:зゝ∠)_

然后通过打表发现n过大时基本都是1.64493,也就是n>=1e6的时候,所以打表的范围有了,就是[1,1e6];

然后用字符串读入n,如果n的长度>=7,直接输出1.64493即可

代码:

#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;
const int N = 1e6+5;
char arr[N];
double f[N];//f[x] the sum before x;
//打表
void table(){
    double ans=0.0;
    for(int i=1; i<=1e6; i++){
        ans += 1.0/i/i;
        f[i] = ans;
    }
}
int main(){
    int n,len;
    table();
    while(~scanf("%s", arr)){
        len = strlen(arr);
        if(len >= 7){
            printf("%.5f\n", f[1000000]);
            continue;
        }
        n = 0;
        for(int i=0; i<len; i++)
            n = 10*n + (arr[i]-'0');
        printf("%.5f\n", f[n]);
    }
    return 0;
}


1004 Tea

题意:

这诗一样的题目描述我很无语,概括一下就是:
两个杯子和一个壶,你要往杯子里倒水,尽可能的倒水次数少;//倒一个杯子就算一次,而不是倒两个杯子才算一次!!!
倒进杯子里的水可见,但壶里剩余水量不知,但你会知道是否空了,且知道壶里水的初始量是[L,R]这个范围;
到最后呢,壶里剩余水<=1个单位,杯子间差<=1个单位

思路:

这种找规律的题就是猜呀猜,然后找特例_(:зゝ∠)_
① r<=1 不需要倒水
② 1<r<=2 倒一次就够
③ r-l<=2 倒两次,第一次填L/2+0.5,第二次填[L-L/2,R-1-L/2](以(6,8)(7,9)为例,满足)

④ 否则,依次倒水L/2, L/2+1, L/2+1-L/2+1, L/2 + (L/2+1-L/2+1) - (L/2+1) +1……如此下去就是 L/2, L/2+1, 2, 2……

可总结规律为(L/2 + L/2+1 + 2 + 2 + ……)(共n次)=(R-1); 即n = (R-L)/2+1;

按照找到的规律写代码即可

代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
/*
这种找规律的题就是猜呀猜,然后找特例
r<=1 不需要倒水
1<r<=2 一次就够
r-l<=2 第一次填L/2+0.5,第二题填[L-L/2,R-1-L/2](以(6,8)(7,9)为例,满足)
否则,依次倒水L/2, L/2+1, L/2+1-L/2+1, L/2 + (L/2+1-L/2+1) - (L/2+1) +1……
如此下去就是 L/2, L/2+1, 2, 2…… 可总结规律为(L/2 + L/2+1 + 2 + 2 + ……)(共n次)=(R-1);
即n = (R-L)/2+1;
*/
using namespace std;
__int64 judge(__int64 l, __int64 r){
    if(r<=1) return 0;
    if(r<=2) return 1;
    if(r-l<=2) return 2;
    l = max(l,1LL);
    return (r-l)/2+1;
}
int main(){
    __int64 l, r;
    while(~scanf("%I64d%I64d", &l, &r)){
        printf("%I64d\n", judge(l,r));
    }
    return 0;
}


1005 Balanced Game

题意:

高中玩过的“rock-scissors-paper-Spock-lizard”游戏,就是“石头剪刀布”的加强版
一共十条关系,每个都制约俩且被俩制约
题目给出这种平衡游戏的形状数目,求能否平衡

思路:

当前形状会制约n/2个形状,且会被n/2个形状指向,所以n = n/2*2+1;
那么n必须是个>=3(首先保证成环)的偶数

代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
/*
高中玩的“rock-scissors-paper-Spock-lizard”游戏,就是“石头剪刀布”的加强版
一共十条关系,每个都制约俩且被俩制约
题目给出这种平衡游戏的形状数目,求能否平衡
当前形状会制约n/2个形状,且会被n/2个形状指向,所以n = n/2*2+1;
n必须是个>=3(首先保证成环)的偶数
*/
using namespace std;
int main(){
    int t, n;
    scanf("%d", &t);
    while(t-->0){
        scanf("%d", &n);
        if(n%2 == 0){
            printf("Bad\n");
            continue;
        }
        printf("Balanced\n");
    }
    return 0;
}


1006 The Best Path

题意:

n个湖,m条河,每个湖有一个value,每经过一次就异或这个当前湖的value,求经过所有河且只经过一次并使异或值最大的异或值;

如果不能经过所有河就输出“Impossible”

思路:

通过图(无向图或有向图)中所有边且每边仅通过一次的通路称为欧拉通路,相应的回路称为欧拉回路。具有欧拉回路的图称为欧拉图(Euler Graph),具有欧拉通路而无欧拉回路的图称为半欧拉图。

根据欧拉图和半欧拉图的定义,我们可以知道这就是我们要求的!

离散数学,判断是否是欧拉图/半欧拉图(奇度为2/0)

先判断是否是欧拉通路(奇度为2),异或所有deep/2%2为奇数的value;
再判断是否是欧拉回路(奇度为0),如果是就枚举起点异或之

代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include<vector>
using namespace std;

const int N = 1e5+5;
int val[N];
int deep[N];
int main(){
    int t, n, m;
    int x, y;
    scanf("%d", &t);
    while(t-->0){
        memset(deep,0,sizeof(deep));
        scanf("%d%d", &n, &m);
        for(int i=1; i<=n; i++)
            scanf("%d", &val[i]);
        while(m-->0){
            scanf("%d%d", &x, &y);
            deep[x]++;
            deep[y]++;
        }
        int tmp=0;
        for(int i=1; i<=n; i++)
        if(deep[i]&1) tmp++;
        if(tmp!=2 && tmp!=0){
            printf("Impossible\n");
            continue;
        }
        //欧拉通路
        int ans = 0;
        for(int i=1; i<=n; i++)
        if(((deep[i]+1)/2)&1)
            ans ^= val[i];
        //欧拉回路-枚举起点
        int re = 0;
        if(tmp==0){
            for(int i=1; i<=n; i++)
                re = max(re,ans^val[i]);
        }
        else
            re = ans;
        printf("%d\n", re);
    }
}


1011 Barricade 是最短路+最小割问题,等看完“最小割”相关知识后再回头做,先搁着_(:зゝ∠)_

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值