Pro
Sco
预计得分: 100+100+?=200 100 + 100 + ? = 200
实际得分: 100+70+?=170 100 + 70 + ? = 170
PS:第三题好麻烦,打了好几节课
Sol
铺瓷砖
很简单的分数求 lcm l c m 的问题
最后答案注意约分,还要特判分母为 1 1 的情况
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int T , A , B , C , D;
long long T1 , T2 , T3;
long long gcd(long long x , long long y) {
while(y) {
int t = x % y;
x = y;
y = t;
}
return x;
}
long long lcm(long long x , long long y) {
return x * y / gcd(x , y);
}
int main() {
scanf("%d",&T);
while(T--) {
scanf("%d%d%d%d",&A,&B,&C,&D);
T1 = lcm(B , D);
T2 = lcm((T1/B)*A , (T1/D)*C);
T3 = gcd(T1 , T2);
if(T1/T3 == 1)
printf("%lld\n",T2/T3);
else
printf("%lld/%lld\n",T2/T3,T1/T3);
}
return 0;
}
小Y的问题
第一次读完题没看到第一问
第一问很简单,就是一个组合数问题:
对于每一个结点,维护出与该结点相连的结点数,存到中
第一问答案即为: ∑ni=1C2ind[i]−1 ∑ i = 1 n C i n d [ i ] − 1 2 , 其中 ind[i]>=3 i n d [ i ] >= 3
化简一下式子就变成了: ∑ni=1(ind[i]−1)(ind[i]−2)2 ∑ i = 1 n ( i n d [ i ] − 1 ) ( i n d [ i ] − 2 ) 2
第二问呢,也是比较好想的:
对于每一个点维护与该点相连的边权的前四大
这样就可以枚举每一个点,枚举的这个点作为 Y Y 字形的中间的那个点
很明显,如果满足条件,一定是所连的边大于等于3,与第一问中一样,就可以一起做的
对于这个点再枚举字形最下面的那个点
第二问答案就是以 Y Y 字形中间的那个点开始的前两大加上以最下面点的第一大
当前要除去已经使用过的点
#include<iostream>
#include<cstdio>
using namespace std;
const int L = 200005;
struct Node {
int to , next;
long long len;
};
Node e[2*L];
struct Tree {
int num;
long long len;
};
Tree maxa[L][5];
int n , head[L] , tot , ind[L];
long long ans1 , ans2;
inline long long mymax(long long a , long long b) { return a>b?a:b; }
void add(int x , int y , long long z) {
tot++;
e[tot].to = y;
e[tot].next = head[x];
e[tot].len = z;
head[x] = tot;
}
void update(int x , int y , long long z) {
for(int i=1; i<=4; i++)
if(z >= maxa[x][i].len) {
for(int j=4; j>=i+1; j--)
maxa[x][j] = maxa[x][j-1];
maxa[x][i].len = z;
maxa[x][i].num = y;
break;
}
for(int i=1; i<=4; i++)
if(z >= maxa[y][i].len) {
for(int j=4; j>=i+1; j--)
maxa[y][j] = maxa[y][j-1];
maxa[y][i].len = z;
maxa[y][i].num = x;
break;
}
}
long long find1(int x , int y) {
long long res = 0 , cnt = 0;
for(int i=1; i<=4; i++)
if(maxa[x][i].num != y) {
cnt++;
res += maxa[x][i].len;
if(cnt == 2)
return res;
}
}
long long find2(int x , int y) {
if(maxa[x][1].num == y)
return maxa[x][2].len;
return maxa[x][1].len;
}
int main() {
freopen("question.in","r",stdin);
freopen("question.out","w",stdout);
scanf("%d",&n);
for(int i=1; i<n; i++) {
int x , y;
long long z;
scanf("%d%d%lld",&x,&y,&z);
ind[x]++;
ind[y]++;
add(x , y , z);
add(y , x , z);
update(x , y , z);
}
for(int i=1; i<=n; i++) {
if(ind[i] < 3)
continue;
long long cnt = (long long)(ind[i]-1)*(ind[i]-2)/2;
for(int j=head[i]; j; j=e[j].next)
if(ind[e[j].to] > 1) {
ans1 += (ind[e[j].to]-1)*cnt;
ans2 = mymax(ans2 , find1(i , e[j].to) + e[j].len + find2(e[j].to , i));
}
}
printf("%lld\n%lld",ans1,ans2);
return 0;
}
水管工的难题
最毒瘤的一道题,尽管只是个搜索……
用曼哈顿距离来进行最优性剪枝
其实不必把每一个方向都求出来
只需要加一或者减一,然后等会搜索的时候乘二或者乘三就行
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstdlib>
using namespace std;
long stime,ttime;
struct Node {
int x , y , z , opt;
bool operator == (const Node &a) const {
return (a.x == x && a.y == y && a.z == z && a.opt == opt);
}
};
Node S , T;
const int dx[] = { 1, -1, 0, 0, 0, 0 }, dy[] = { 0, 0, 1, -1, 0, 0 }, dz[] = { 0, 0, 0, 0, 1, -1 };
int X , Y , Z , n , vis[25][25][25] , ans = 13 , za[25][25][25] , sdir , tdir;
char c;
inline int myabs(int a) { return a<0?(-a):a; }
inline int mymin(int a , int b) { return a<b?a:b; }
int jud(int x , int y , int z) {
if (x >= 1 && x <= X && y >= 1 && y <= Y && z >= 1 && z <= Z && !vis[x][y][z] && !za[x][y][z])
return 1;
return 0;
}
void dfs(Node x , int cnt) {
int dis = myabs(T.x-x.x) + myabs(T.y-x.y) + myabs(T.z-x.z);
if(cnt + dis/4 >= ans || cnt + dis/4 > 12)
return ;
if(x == T) {
ans = mymin(ans , cnt);
return ;
}
if(jud(x.x+dx[x.opt] , x.y+dy[x.opt] , x.z+dz[x.opt]) && jud(x.x+2*dx[x.opt] , x.y+2*dy[x.opt] , x.z+2*dz[x.opt])) {
vis[x.x+dx[x.opt]][x.y+dy[x.opt]][x.z+dz[x.opt]] = vis[x.x+2*dx[x.opt]][x.y+2*dy[x.opt]][x.z+2*dz[x.opt]] = 1;
int nx = x.x+2*dx[x.opt] , ny = x.y+2*dy[x.opt] , nz = x.z+2*dz[x.opt];
for(int i=0; i<6; i++) {
if(i/2 != x.opt/2) {
if(jud(nx+dx[i] , ny+dy[i] , nz+dz[i]) && jud(nx+2*dx[i] , ny+2*dy[i] , nz+2*dz[i])) {
vis[nx+dx[i]][ny+dy[i]][nz+dz[i]] = vis[nx+2*dx[i]][ny+2*dy[i]][nz+2*dz[i]] = 1;
Node t;t.x= nx+2*dx[i] , t.y = ny+2*dy[i] , t.z = nz+2*dz[i] , t.opt = i;
dfs(t , cnt+1);
vis[nx+dx[i]][ny+dy[i]][nz+dz[i]] = vis[nx+2*dx[i]][ny+2*dy[i]][nz+2*dz[i]] = 0;
}
}
}
if(jud(x.x+3*dx[x.opt] , x.y+3*dy[x.opt] , x.z+3*dz[x.opt])) {
vis[x.x+3*dx[x.opt]][x.y+3*dy[x.opt]][x.z+3*dz[x.opt]] = 1;
int nx = x.x+3*dx[x.opt] , ny = x.y+3*dy[x.opt] , nz = x.z+3*dz[x.opt];
for(int i=0; i<6; i++) {
if(i/2 != x.opt/2) {
if(jud(nx+dx[i] , ny+dy[i] , nz+dz[i])) {
vis[nx+dx[i]][ny+dy[i]][nz+dz[i]] = 1;
Node t;t.x= nx+dx[i] , t.y = ny+dy[i] , t.z = nz+dz[i] , t.opt = i;
dfs(t , cnt+1);
vis[nx+dx[i]][ny+dy[i]][nz+dz[i]] = 0;
}
}
}
vis[x.x+3*dx[x.opt]][x.y+3*dy[x.opt]][x.z+3*dz[x.opt]] = 0;
}
vis[x.x+dx[x.opt]][x.y+dy[x.opt]][x.z+dz[x.opt]] = 0;
vis[x.x+2*dx[x.opt]][x.y+2*dy[x.opt]][x.z+2*dz[x.opt]] = 0;
}
}
int main() {
freopen("plumber.in","r",stdin);
freopen("plumber.out","w",stdout);
stime = clock();
scanf("%d%d%d%d",&X,&Y,&Z,&n);
scanf("%d%d%d",&S.x,&S.y,&S.z);
cin>>c;
sdir = (c - 'x') * 2;
if (c == 'x')
sdir += (S.x == X);
if (c == 'y')
sdir += (S.y == Y);
if (c == 'z')
sdir += (S.z == Z);
S.x -= dx[sdir];
S.y -= dy[sdir];
S.z -= dz[sdir];
S.opt = sdir;
scanf("%d%d%d",&T.x,&T.y,&T.z);
cin>>c;
tdir = (c - 'x') * 2;
if (c == 'x')
tdir += (T.x == 1);
if (c == 'y')
tdir += (T.y == 1);
if (c == 'z')
tdir += (T.z == 1);
T.opt = tdir;
for(int i=1; i<=n; i++) {
int x , y , z;
scanf("%d%d%d",&x,&y,&z);
za[x][y][z] = 1;
}
dfs(S , 0);
if(ans == 13)
printf("impossible\n");
else
printf("%d\n",ans);
ttime = clock();
// cout<<"AC time:"<<ttime-stime<<"ms";
return 0;
}