# 【11.6校内测试】【倒计时4天】【找规律？思维】【二分+倍增】

Solution

Code

#include<bits/stdc++.h>
using namespace std;

struct Node {
int v, nex;
} Edge[2000005];

int h[1000005], stot;
void add(int u, int v) {
Edge[++stot] = (Node) {v, h[u]};
h[u] = stot;
}

int siz[1000005];
void dfs(int u, int f) {
siz[u] = 1;
for(int i = h[u]; i; i = Edge[i].nex) {
int v = Edge[i].v;
if(v == f)    continue;
dfs(v, u);
siz[u] += siz[v];
}
}

int main() {
freopen("count.in", "r", stdin);
freopen("count.out", "w", stdout);
int n;
scanf("%d", &n);
for(int i = 1; i < n; i ++)    {
int u, v;
scanf("%d%d", &u, &v);
}
dfs(1, 0);
int ans = 0;
for(int i = 1; i <= n; i ++) {
if(n % i == 0) {
int now = 0;
for(int j = 1; j <= n; j ++)
if(siz[j] % i == 0)    now ++;
if(now == n / i)    ans ++;
}
}
printf("%d", ans);
return 0;
}

Solution

【注意！】跳倍增要先减再跳第二次错了555555！！！

Code

#include<bits/stdc++.h>
using namespace std;

int n, m;
int jum[200005][21], val[200005][21], to[200005][21];
int t[200005], mi;

void init() {
for(int i = 1; i <= 2 * n; i ++)
jum[i][0] = i + 1,
val[i][0] = t[i];
for(int p = 0; p <= 20; p ++)    jum[2 * n + 1][p] = 2 * n + 1;
for(int p = 1; p <= 20; p ++)
for(int i = 1; i <= 2 * n; i ++)
jum[i][p] = jum[jum[i][p - 1]][p - 1],
val[i][p] = val[i][p - 1] + val[jum[i][p - 1]][p - 1];
}

void jump(int mid) {
for(int j = 1; j <= 2 * n; j ++) {
int QAQ = mid, u = j;
for(int i = 20; i >= 0; i --)
if(QAQ >= val[u][i])    QAQ -= val[u][i], u = jum[u][i]; ///////先减再跳！！！！
to[j][0] = u;
}
for(int i = 0; i <= 20; i ++)    to[2 * n + 1][i] = 2 * n + 1;
for(int p = 1; p <= 20; p ++)
for(int i = 1; i <= 2 * n; i ++)
to[i][p] = to[to[i][p - 1]][p - 1];
}

bool check(int mid) {
jump(mid);
for(int i = 1; i <= n; i ++) {
int u = i, M = m, t = 0;
while(M) {
if(M & 1)    u = to[u][t];
M >>= 1, t ++;
}
if(u >= i + n)    return 1;
}
return 0;
}

int erfen() {
int l = mi, r = 50000000, ans;
while(l <= r) {
int mid = (l + r) >> 1;
if(check(mid))    ans = mid, r = mid - 1;
else    l = mid + 1;
}
return ans;
}

int main() {
freopen("dinner.in", "r", stdin);
freopen("dinner.out", "w", stdout);
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++)    scanf("%d", &t[i]), t[i + n] = t[i], mi = max(mi, t[i]);
init();
int ans = erfen();
printf("%d", ans);
return 0;
}

posted @ 2018-11-06 17:16  Wans_ovo  阅读(109)  评论(0编辑  收藏