哎呀呀,终于是一天真正的赛区难度了!
然后_aoao_love_ak就很愉快的AK了....
Terrible!!!!
set水爆了,暴力加个读入优化对于随机数据简直是分分钟AC呀,40组数据0.5s多竟然是Rank1...不过号神充满恶意的数据简直要T成翔。
然后是eat,我做过呀!!WA 10,然后我又吧TYVJ上的AC代码提交,WA 10!!!郁闷...
loop我yy了一个组合数,然后整数被0除...(写丑了?),标程竟然数据分治....
-----------------------------------------------------------------------------
set
set|set.in|set.out
题目描述:
维护一个可重集,支持:
插入一个正整数
询问一个正整数k,集合中有多少个数是k的倍数
输入格式:
第一行一个整数N,表示操作数量。
接下来N行,每行两个整数a,b
如果a=1,表示向集合插入一个数b
如果a=2,询问有多少个数是b的倍数
输出格式:
输出一行一个整数,表示所有询问的答案的亦或和(不要想多,只是防cena智障)
样例输入:
5
1 2
1 3
2 2
1 6
2 3
样例输出:
3
数据范围:
共40组数据
对于第i组数据,n==1000*i,所有的b<=n
每组数据时限0.5秒
题解:
暴力...
1 #define NOMBRE "set"
2 #include <cstdio>
3 #include <cstring>
4
5 const int MAXN = 40000;
6
7 char InputC;
8 int n, Q, a, b, Pri, Max, cj[MAXN+10];
9 bool anna = false;
10
11 inline int NextInt(){
12 int ret = 0;
13 do
14 InputC = getchar();
15 while (!(48<=InputC && InputC<=97));
16 do
17 ret *= 10, ret += InputC-48, InputC = getchar();
18 while (48<=InputC && InputC<=97);
19
20 return ret;
21 }
22
23 inline void Query(int x){
24 int ret = 0;
25 for (register int i=x; i<=Max; i+=x)
26 ret += cj[i];
27 if (!anna) Pri = ret, anna = true;
28 else Pri ^= ret;
29 }
30
31 int main(){
32 freopen(NOMBRE ".in", "r", stdin);
33 freopen(NOMBRE ".out", "w", stdout);
34
35 memset(cj, 0, sizeof(cj));
36
37 Q = NextInt(), Max = 0;
38 for (register int i=0; i<Q; i++){
39 a = NextInt(), b = NextInt();
40 if (a==1){
41 cj[b] ++;
42 if (b>Max) Max = b;
43 }
44 else Query(b);
45 }
46 printf("%d
", Pri);
47 }
-----------------------------------------------------------------------------
eat
eat|eat.in|eat.out
题目描述:
在某一颗行星上,有一种奇特的食物网,这个食物网中只有三个营养级A,B,C,满足A中的生物只吃B中的生物,B中的生物只吃C中的生物,C中的生物只吃A中的生物。
现在,依次给出一些生物之间的关系,判断关系是否成立。一条关系成立当且仅当它不与之前的所有成立的关系矛盾且不自相矛盾。
输入格式:
第一行两个个整数N,M分别表示生物的数量和关系数量
接下来M行:每行三个整数q,x,y
如果q=0:表示x号生物与y号生物属于同一营养级
如果q=1:表示x号生物要吃y号生物
输出格式:
一行一个整数,表示成立的关系数量
样例输入:
100 6
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5
样例输出:
4
数据范围:
30% N,M<=100
50% N,M<=3000
100% N,M<=100000
题解:
做三个并查集,分别表示同类、吃、被吃
1 #define NOMBRE "eat"
2 #include <cstdio>
3
4 const int MAXN = 100000*3+10;
5
6 int n, m, Pri, f[MAXN];
7
8 inline int find(int x){
9 return (f[x]==x) ? x : f[x]=find(f[x]);
10 }
11
12 inline void link(int x,int y){
13 f[find(x)] = find(y);
14 }
15
16 inline int Cal(){
17 int a1, a2, a3, b1, b2, b3, a, b, d;
18
19 scanf("%d %d %d", &d, &a, &b);
20
21 if ((d==2 && a==b) || a>n || b>n) return 0;
22
23 a1 = find(a), a2 = find(a+n), a3 = find(a+n+n);
24 b1 = find(b), b2 = find(b+n), b3 = find(b+n+n);
25
26 if (d==1 && a1!=b3 && a1!=b2 && b1!=a2 && b1!=b3){
27 link(a, b), link(a+n, b+n), link(a+n+n, b+n+n);
28 return 1;
29 }
30 if (d==1) return 0;
31
32 if (d==2 && a1!=b1 && a2!=b1 && b3!=a1){
33 link(a, b2), link(a3, b1), link(a2, b3);
34 return 1;
35 }
36 if (d==2) return 0;
37 }
38
39 int main(){
40 freopen(NOMBRE ".in", "r", stdin);
41 freopen(NOMBRE ".out", "w", stdout);
42
43 scanf("%d %d", &n, &m), Pri = 0;
44 for (register int i=0; i<=3*n; i++)
45 f[i] = i;
46 for (register int i=0; i<m; i++)
47 Pri += Cal();
48 printf("%d
", Pri);
49 }
-----------------------------------------------------------------------------
loop
loop|loop.in|loop.out
题目描述:
有N个点。
现在重复这样的操作:
随机找一个出度为0的点p1,随机找一个入度为0的点p2,连一条有向边从p1指向p2。直到没有出度为0的点。
统计最终状态这个图中的环的期望个数。
为了保证答案精度,提供另外一个参数W(正整数),请你输出小于你的答案乘上W后的最大整数。
输入格式:
一行两个整数N,W。
输出格式:
一行一个整数(保证不超过10^6)。
样例输入(多组,测试数据中只有一组):
1 100
2 100
样例输出:
99
149
数据范围:
30% N<=100
70% N<=5*10^6
100% N<=10^18
题解:
可以发现答案就是∑1/i
但是由于N<=10^18,所以就....
百度“欧拉常数”和“调和级数”,然后数据分治...
1 #define NOMBRE "loop"
2 #include <cmath>
3 #include <cstdio>
4 #include <cstring>
5 #define LL "%I64d"
6
7 const int MAXN = 5*1e5;
8
9 int Pri, k;
10 long long n;
11 double cj = 0.0;
12
13 int main(){
14 freopen(NOMBRE ".in", "r", stdin);
15 freopen(NOMBRE ".out", "w", stdout);
16
17 scanf(LL "%d", &n, &k);
18 if (n<=MAXN)
19 for (register int i=1; i<=n; i++)
20 cj += 1.0/(double)i;
21 else cj = 0.57721+log(n);
22 Pri = (int)floor(k*cj);
23 printf("%d
", Pri);
24 }