A
SBT,直接搜索即可
int n, ans ;
int x[N], y[N], vis[N] ;
void dfs(int i) {
vis[i] = 1 ;
rep(j, 1, n)
if (!vis[j] && (x[i] == x[j] || y[i] == y[j]))
dfs(j) ;
}
signed main() {
scanf("%d", &n) ;
rep(i, 1, n) scanf("%d%d", &x[i], &y[i]) ;
rep(i, 1, n)
if (!vis[i]) {
ans++ ;
dfs(i) ;
}
printf("%d
", ans - 1) ;
return 0 ;
}
B
这个题蛮有意思的
刚开始看还没什么思路
然后观察一下就大概知道了
首先枚举结束之后另外一个数的值是什么
然后考虑这种状态是怎么达到的
假如当前的状态为 ([a,b](a<b))
(1) 次操作我们可以达到 ([b,a+b])
(2) 次操作我们可以到达 ([b,a+2*b]) 和 ([a+2*b,a+b])
any idea?
是不是有点像辗转相减,???
然后大概就会了吧
模拟 (gcd) 的过程
从 (gcd(a,b)) 变成 (gcd(b,a\%b)) 的 (mistake~size) 就是 ((a/b-1)) (特判 (b=1) 的情况)
转移时的还要维护一个步数,每次加 (a/b)
然后就 (AC) 了
这个 (Div2D) 质量还不错,(大雾)
int n, r, cur, mst, ans, ansid ;
int gcd(int a, int b) {
if (!b) return a ;
cur += a / b ;
mst += max(0, a / b - 1) ;
if (b == 1 && a > 1) mst-- ;
return gcd(b, a % b) ;
}
int col = 0 ;
char op[] = {'T', 'B'} ;
void solve(int a, int b) {
if (b == 0) return ;
solve(b, a % b) ;
if (b == 1 && a > 1) {
putchar(op[col]) ;
col ^= 1 ;
per(i, a / b - 1, 1) putchar(op[col]) ;
} else {
per(i, a / b, 1) putchar(op[col]) ;
}
if (a / b) col ^= 1 ;
return ;
}
signed main() {
ans = iinf ;
scanf("%d%d", &n, &r) ;
rep(i, 0, r) {
cur = mst = 0 ;
if (gcd(i, r) != 1 || cur != n) continue ;
if (mst < ans) { ans = mst ; ansid = i ; }
}
if (ans == iinf) print("IMPOSSIBLE") ;
printf("%d
", ans) ;
solve(ansid, r) ;
return 0 ;
}