NOIP模拟62

T1:

  没有想到是一道比较简单的鸽巢,关键点在于n个数并对n取模

考虑从特殊的模数n入手,于是可以发现,序列前缀和共有n种取值

当前缀和模n为0时显然直接输出即可,因此相当于n个数放入n-1个

抽屉种,显然必然会出现重复,因此一段连续区间中一定存在解

代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define I int
 4 #define C char
 5 #define B bool
 6 #define V void
 7 #define D double
 8 #define LL long long
 9 #define UI unsigned int
10 #define UL unsigned long long
11 #define P pair<I,I>
12 #define MP make_pair
13 #define a first
14 #define b second
15 #define debug cout << "It's Ok Here !" << endl;
16 #define lowbit(x) (x & -x)
17 const I N = 1e6 + 3;
18 I n,s,last[N];
19 inline I read () {
20     I x(0),y(1); C z(getchar());
21     while (!isdigit(z)) { if (z == '-') y = -1; z = getchar(); }
22     while ( isdigit(z))  x = x * 10 + (z ^ 48), z = getchar();
23     return x * y;
24 }
25 inline V Max (I &a,I b) { a = a > b ? a : b; }
26 inline V Min (I &a,I b) { a = a < b ? a : b; }
27 inline I max (I a,I b) { return a > b ? a : b; }
28 inline I min (I a,I b) { return a < b ? a : b; }
29 inline V swap (I &a,I &b) { a ^= b, b ^= a, a ^= b; }
30 inline I abs (I a) { return a >= 0 ? a : -a; }
31 inline P operator + (const P &a,const P &b) {
32     return MP (a.a + b.a,a.b + b.b);
33 }
34 inline P operator - (const P &a,const P &b) {
35     return MP (a.a - b.a,a.b - b.b);
36 }
37 signed main () {
38     n = read(); 
39     for (I i(1);i <= n; ++ i) {
40         (s += read()) %= n;
41         if (s == 0) {
42             printf ("%d\n",i);
43             for (I j(1);j <= i; ++ j)
44                 printf ("%d ",j);
45             exit (0);
46         }
47         if (last[s]) {
48             printf ("%d\n",i - last[s]);
49             for (I j(last[s] + 1);j <= i; ++ j)
50                 printf ("%d ",j);
51             exit (0);
52         }
53         else last[s] = i;
54     }
55     puts ("-1");
56 }
View Code

T2:

  考场基本上想到正解,然而最后统计答案时直接输出cnt - 1

,显然的优化空间,考虑如何避开数组,与之前一道CF题的形式

相似,考虑当存在某一颜色长度大于n >> 1时显然无解,于是可以

利用栈模型,只需要尾指针判断是否存在该颜色,(仅判断是否

存在一种颜色大于n >> 1,并不需要具体颜色)在通过id记录颜色

最终再判断需要删几个即可

代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define I int
 4 #define C char
 5 #define B bool
 6 #define V void
 7 #define D double
 8 #define LL long long
 9 #define UI unsigned int
10 #define UL unsigned long long
11 #define P pair<I,I>
12 #define MP make_pair
13 #define a first
14 #define b second
15 #define lowbit(x) (x & -x)
16 #define debug cout << "It's Ok Here!" << endl;
17 #define log(x) ((I)log2(x))
18 const I M = 1e3 + 3;
19 I m,k,color,cnt,W[M],X[M],Y[M],Z[M];
20 inline LL read () {
21     LL x(0),y(1); C z(getchar());
22     while (!isdigit(z)) { if (z == '-') y = -1; z = getchar(); }
23     while ( isdigit(z))  x = x * 10 + (z ^ 48), z = getchar();
24     return x * y;
25 }
26 inline V Max (I &a,I b) { a = a > b ? a : b; }
27 inline V Min (I &a,I b) { a = a < b ? a : b; }
28 inline I max (I a,I b) { return a > b ? a : b; }
29 inline I min (I a,I b) { return a < b ? a : b; }
30 inline V swap (I &a,I &b) { a ^= b, b ^= a, a ^= b; }
31 inline I abs (I a) { return a >= 0 ? a : -a; }
32 inline P operator + (const P &a,const P &b) {
33     return MP (a.a + b.a,a.b + b.b);
34 }
35 inline P operator - (const P &a,const P &b) {
36     return MP (a.a - b.a,a.b - b.b);
37 }
38 signed main () {
39     m = read(), k = read();
40     for (I i(1);i <= m; ++ i) 
41         W[i] = read();
42     for (I i(1);i <= m; ++ i)
43         X[i] = read();
44     for (I i(1);i <= m; ++ i)
45         Y[i] = read();
46     for (I i(1);i <= m; ++ i)
47         Z[i] = read();
48     I s ((1 << k) - 1); color = LONG_LONG_MIN;
49     for (I i(1);i <= m; ++ i) {
50         LL last (X[i]); 
51         if (cnt && last != color) {
52             if (-- cnt == 0) cnt ++ , color = last;
53         }
54         else cnt ++ , color = last;
55         for (I j(1);j < W[i]; ++ j) {
56             last = (last * Y[i] + Z[i]) & s;
57             if (cnt && last != color) {
58                 if (-- cnt == 0) cnt ++ , color = last;
59             }
60             else cnt ++ , color = last;
61         }
62     }
63     if (!cnt) { puts ("0"); exit (0); }
64     cnt = 0; I oth(0);
65     for (I i(1);i <= m; ++ i) {
66         LL last (X[i]);
67         last == color ? cnt ++ : oth ++ ;
68         for (I j(1);j < W[i]; ++ j) {
69             last = (last * Y[i] + Z[i]) & s;
70             last == color ? cnt ++ : oth ++ ;
71         }
72     }
73     printf ("%d\n",max (cnt - oth - 1,0ll));
74 }
View Code

T3:

  理解错题意,事实上当不考虑0边权时是一个比较简单的问题

若存在d(u,v) = d(u,k) + d(k,v)那么显然u,v边可以任意选择

  考虑0边权的影响,显然为由于边权不增导致重复计算,于是

考虑如何计数,考虑当且仅当0边权形成一个个完全图时有解,否则

其内部的边最小值一定为0,并且若干完全图之间的边权一定相等

同理,于是首先考虑完全图之间的边,通过统计边权相同边数利用

简单容斥原理可以转化为不包含0边权的问题

  考虑完全图内部的计数,于是直接根据问题设f[i]为存在i个点

的图的方案数,很容易想到容斥,对应的钦定j点为完全图,那么

剩余i-j个点任意选择,需要考虑两部分之间的边数为i * (n - i),由

于钦定,所以这部分贡献为k^(i * (n - i))(强制不选0),再计算

方案数为C(i - 1,j - 1),这里应用到的计数DP trick为在状态相互包

含时利用钦定点属于合法集来避免重复计算,因此为C(i - 1,j - 1)

代码如下:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define I long long
  4 #define C char
  5 #define B bool 
  6 #define V void
  7 #define D double
  8 #define LL long long
  9 #define UI unsigned int
 10 #define UL unsigned long long
 11 #define P pair<I,I>
 12 #define MP make_pair
 13 #define a first
 14 #define b second
 15 #define lowbit(x) (x & -x)
 16 const I N = 405, mod = 998244353;
 17 I n,t,ans(1),d[N][N],J[N],Y[N],F[N],G[N];
 18 inline I read () {
 19     I x(0),y(1); C z(getchar());
 20     while (!isdigit(z)) { if (z == '-') y = -1; z = getchar(); }
 21     while ( isdigit(z))  x = x * 10 + (z ^ 48), z = getchar();
 22     return x * y;
 23 }
 24 inline V Max (I &a,I b) { a = a > b ? a : b; }
 25 inline V Min (I &a,I b) { a = a < b ? a : b; }
 26 inline I max (I a,I b) { return a > b ? a : b; }
 27 inline I min (I a,I b) { return a < b ? a : b; }
 28 inline V swap (I &a,I &b) { a ^= b, b ^= a, a ^= b; }
 29 inline I abs (I a) { return a >= 0 ? a : -a; }
 30 inline P operator + (const P &a,const P &b) {
 31     return MP (a.a + b.a,a.b + b.b);
 32 }
 33 inline P operator - (const P &a,const P &b) {
 34     return MP (a.a - b.a,a.b - b.b);
 35 }
 36 inline I fp (I a,I b) {
 37     I ans(1);
 38     for (; b ;b >>= 1, a = a * a % mod)
 39         if (b & 1) ans = ans * a % mod;
 40     return ans;
 41 }
 42 inline I _C (I n,I m) {
 43     if (!m || n == m) return 1;
 44     return J[n] * Y[m] % mod * Y[n - m] % mod;
 45 }
 46 struct DJS {
 47     I f[N],size[N];
 48     I get (I x) { 
 49         return x == f[x] ? x : f[x] = get (f[x]); 
 50     }
 51     inline V merge (I x,I y) {
 52         I fx (get (x)), fy (get (y));
 53         if (fx == fy) return ; 
 54         f[fy] = fx; size[fx] += size[fy];
 55     }
 56 }DJS;
 57 signed main () {
 58     n = read(), t = read();
 59     for (I i(1);i <= n; ++ i)
 60         DJS.f[i] = i, DJS.size[i] = 1;
 61     for (I i(1);i <= n; ++ i) {
 62       for (I j(1);j <= n; ++ j) 
 63         d[i][j] = read();
 64       if (d[i][i]) puts ("0"), exit (0);
 65     }
 66     for (I k(1);k <= n; ++ k) 
 67       for (I i(1);i <= n; ++ i)
 68         for (I j(1);j <= n; ++ j) 
 69           if (d[i][k] + d[k][j] < d[i][j])
 70             puts ("0"), exit (0);
 71     for (I i(1);i <= n; ++ i) 
 72       for (I j(1);j <  i; ++ j) {
 73         if (d[i][j] == 0) DJS.merge (i,j);
 74         if (d[i][j] != d[j][i] || d[i][j] > t)
 75             puts ("0"), exit (0);
 76       }
 77     J[0] = Y[0] = 1;
 78     for (I i(1);i <= n; ++ i) 
 79         J[i] = J[i - 1] * i % mod;
 80     Y[n] = fp (J[n],mod - 2);
 81     for (I i(n - 1); i; -- i)
 82         Y[i] = Y[i + 1] * (i + 1) % mod;
 83     for (I i(1);i <= n; ++ i) {
 84         F[i] = G[i] = fp (t + 1,i * (i - 1) >> 1);
 85         for (I j(1);j <  i; ++ j) {
 86             (F[i] -= F[j] * G[i - j] % mod * _C (i - 1,j - 1) % mod * fp (t,j * (i - j) % mod)) %= mod;
 87             if (DJS.f[i] != i || DJS.f[j] != j) continue;
 88             B jud(0); 
 89             for (I k(1);k <= n; ++ k) {
 90                 I tmp (DJS.get (k));
 91                 if (tmp != i && tmp != j && d[i][j] == d[i][tmp] + d[tmp][j]) {
 92                     jud = 1, ans = ans * fp (t - d[i][j] + 1,DJS.size[i] * DJS.size[j]) % mod; break;
 93                 }
 94             }
 95             if (!jud) ans = ans * (fp (t - d[i][j] + 1,DJS.size[i] * DJS.size[j]) - fp (t - d[i][j],DJS.size[i] * DJS.size[j])) % mod;
 96         }
 97     }
 98     for (I i(1);i <= n; ++ i) if (DJS.f[i] == i)
 99         ans = ans * F[DJS.size[i]] % mod;
100     printf ("%lld\n",(ans + mod) % mod);
101 }
View Code

 T4:

  直接口胡,比较容易发现转化题意可得实际是要求任意时刻

中位数需要小于等于剩余所有数,考虑首先O(n)遍历插入

  维护中位数采用经典的对顶堆做法做到O(logn),考虑直观想法

是枚举剩余数判断插入该数后是否满足上述条件,然而时间复杂度跌至

O(n^2),考虑问题显然具有单调性,于是可以对序列排序后进行二分

  然而发现线性结构删除元素基本在O(n),非线性结构又无法进行

二分,然而事实上O(n^2)的做法卡常可过

posted @ 2021-09-26 21:44  HZOI_LYM  阅读(35)  评论(0编辑  收藏  举报