【NOIP2017提高A组模拟8.25】影子
2017-08-25 16:10
435 查看
Description:
1<=n<=10^5
题解:
首先对于这种树上路径问题是很容易想到点分治的,细节比较复杂,也许需要一个set,常数爆炸。比较联赛的做法是并查集。
先将点按权值从大到小排序。
依次枚举每个点,将它和与它相邻且权值大于它的点合并成一棵树。
每次合并,新树的直径的端点一定是原来两棵树中的两条直径的四个端点中的两个,这个易证。
直径上的最小值不一定是当前的点,但是这没有关系,因为它一定在前面就被计算过了。所以ans=max(ans,直径长度×当前点权)
Code:
#include<cstdio> #include<algorithm> #define ll long long #define fo(i, x, y) for(int i = x; i <= y; i ++) using namespace std; const int mo = 1 << 30; const int N = 4000; int T, n, m, p , mu[N + 5]; bool bz[N + 5]; ll ans; void Build() { mu[1] = 1; fo(i, 2, N) { if(!bz[i]) p[++ p[0]] = i, mu[i] = -1; fo(j, 1, p[0]) { int k = i * p[j]; if(k > N) break; bz[k] = 1; if(i % p[j] == 0) { mu[k] = 0; break; } mu[k] = -mu[i]; } } } int main() { Build(); for(scanf("%d", &T); T; T --) { scanf("%d %d", &n, &m); if(n > m) swap(n, m); n --; m --; ans = 0; fo(i, 1, n) if(mu[i] != 0) { int sf, sg; int c = n / i, c2 = (n + 1) / 2 / i, s; sf = (1 + c2) * c2 / 2 * i; sf += (n + 1) * (c - c2) - (c2 + 1 + c) * (c - c2) / 2 * i; c = m / i, c2 = (m + 1) / 2 / i, s; sg = (1 + c2) * c2 / 2 * i; sg += (m + 1) * (c - c2) - (c2 + 1 + c) * (c - c2) / 2 * i; int s1 = (n + 1) * (n / i) - (n / i) * (n / i + 1) * i / 2; int s2 = (m + 1) * (m / i) - (m / i) * (m / i + 1) * i / 2; ans += mu[i] * (sf * s2 + sg * s1 - sf * sg); } ans *= 2; ans += n + m + 2; ans = (ans % mo + mo) % mo; printf("%lld\n", ans); } }
相关文章推荐
- 【jzoj5338】【NOIP2017提高A组模拟8.25】【影子】【点分治】
- 【NOIP2017提高A组模拟8.25】夜莺与玫瑰
- 【NOIP2017提高A组模拟10.7】Confess
- 【NOIP2017提高A组模拟10.10】总结
- 【NOIP2017提高A组模拟8.16】花花的森林
- 空【NOIP2017提高A组模拟8.24】
- 【NOIP2017提高A组模拟7.8】为了爱情 八数码拓展
- 【NOIP2017提高组模拟12.17】向再见说再见
- 【NOIP2017提高组模拟12.24】C
- 【NOIP2017提高A组模拟9.5】遥远的金字塔 斜率优化详解
- A【NOIP2017提高组模拟12.18】
- JZOJ 100035【NOIP2017提高A组模拟7.10】区间
- 【NOIP2017提高A组模拟7.13】第K小数
- 【NOIP2017提高组模拟12.24】B
- 【NOIP2017提高A组模拟10.5】Ping
- 【NOIP2017提高A组模拟10.5】Snake vs Block
- 【NOIP2017提高A组模拟10.10】Permutation
- (前缀和排序)NOIP2017提高组模拟 Day1P1 小A的数学
- 【NOIP2017提高A组模拟8.23】密码
- B【NOIP2017提高组模拟12.18】