Luogu P1494 [国家集训队] 小 Z 的袜子
[国家集训队] 小 Z 的袜子
题目描述
upd on 2020.6.10 :更新了时限。
作为一个生活散漫的人,小 Z 每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿。终于有一天,小 Z 再也无法忍受这恼人的找袜子过程,于是他决定听天由命……
具体来说,小 Z 把这
你的任务便是告诉小 Z,他有多大的概率抽到两只颜色相同的袜子。当然,小 Z 希望这个概率尽量高,所以他可能会询问多个
然而数据中有 0/1
。
输入格式
输入文件第一行包含两个正整数
输出格式
包含 0/1
,否则输出的
样例 #1
样例输入 #1
6 4 1 2 3 3 3 2 2 6 1 3 3 5 1 6
样例输出 #1
2/5 0/1 1/1 4/15
提示
题解
可以全部用等差数列做。
具体做法是每次插入一个颜色就对原先的分子和分母进行更新。也就是先减去这个原先颜色个数的等差数列,然后加上更新后后颜色个数的等差数列。
如原先的颜色个数是x个,那么原先这个颜色的所能选中的情况是
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> using namespace std; long long n, m, block; long long l = 1, r = 0; long long a[5211314], pos[5211314], cnt[5211314], numerator, denominator; //numerator分子 denominator分母 struct ASK { long long l, r, id; }ask[5211314]; struct ANS { long long numerator, denominator; //答案的分子 分母 }ans[5211314]; inline long long read() { long long x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch - '0'); ch = getchar(); } return x * f; } inline bool cmp(ASK a, ASK b) { if (pos[a.l] != pos[b.l]) return pos[a.l] < pos[b.l]; else return a.r < b.r; } inline void Add(long long x) { if (cnt[a[x]] >= 1) { if (cnt[a[x]] != 1) numerator -= ((cnt[a[x]] - 1 + 1) * (cnt[a[x]] - 1) / 2); //只有cnt[a[x]]不为1的时候才用减去原先颜色a[x]的选择数 numerator += ((cnt[a[x]] + 1) * (cnt[a[x]]) / 2); } cnt[a[x]] ++; denominator ++; return; } inline void Del(long long x) { if (cnt[a[x]] >= 2) { numerator -= ((cnt[a[x]] - 1 + 1) * (cnt[a[x]] - 1) / 2); if (cnt[a[x]] != 2) numerator += ((cnt[a[x]] - 1 - 1 + 1) * (cnt[a[x]] - 1 - 1) / 2); //只有cnt[a[x]]不为2(也就是减之后cnt[a[x]]不为1)的时候才用加新颜色a[x]的选择数 } cnt[a[x]] --; denominator --; return; } int main() { n = read(); m = read(); block = sqrt(n); for (long long i = 1; i <= n; ++ i) { a[i] = read(); pos[i] = (i - 1) / block + 1; } for (long long i = 1; i <= m; ++ i) { ask[i].l = read(); ask[i].r = read(); ask[i].id = i; } stable_sort(ask + 1, ask + 1 + m, cmp); for (long long i = 1, temp, temp2; i <= m; ++ i) { while (ask[i].l < l) Add(-- l); while (r < ask[i].r) Add(++ r); while (l < ask[i].l) Del(l ++); while (ask[i].r < r) Del(r --); temp2 = (denominator - 1 + 1) * (denominator - 1) / 2; //记得给分母等差数列 if (numerator != 0) { temp = __gcd(numerator, temp2);//求最大公约数 ans[ask[i].id].numerator = numerator / temp; } else {//若分子为0 temp = temp2; ans[ask[i].id].numerator = 0; } ans[ask[i].id].denominator = temp2 / temp; } for (long long i = 1; i <= m; ++ i) { printf("%lld/%lld\n", ans[i].numerator, ans[i].denominator); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!