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 是最短路+最小割问题,等看完“最小割”相关知识后再回头做,先搁着_(:зゝ∠)_