[关闭]
@2368860385 2020-11-07T03:05:27.000000Z 字数 3344 阅读 243

day9

正睿提高


T1

一共有个人参加了考试。
无聊的助教决定不告诉大家每个人的名次,而是让大家自己猜。
首先,大家知道了第个人的名次区间是
除此之外,又有条其他信息,形如,表示第个人考的要比好(即排名更低)。
现在,小S想要知道,是否有一个合法的排名,满足上述所有的要求。如果有,请输出任意一组解(输出第i名的id),否则输出"-1"(不含括号)。

分析:
题目其实有两个限制:排名在[L,R]之间,u的排名小于v的排名。
对于第二个相当于是一张图,拓扑排序一下。(首先判断不能有环)。
利用拓扑序将[L,R]的限制收紧,u->v,R[u]=min(R[u],R[v]-1])。然后此时就消去了第二个限制。
考虑第一个限制:肯定是贪心的选。那么如何贪心?
从第一个开始枚举第i名的是谁,然后将L在i之前的都加入到一个队列里,(就是说这些点可能在第i个位置,毕竟L<=i了),然后从这些点中选一个右端点最小的,让它在第i个点就行了。
这里加入小于等于i的点的时候,不能直接暴力用vector直接记录下所有左端点在i的。因为即使是R[i]拓扑后,前一个的R一定小于等于下一个的R,但是L的限没有去掉。如果存在这样的情况,1->2,L[1]=6,R[1]=7,L[2]=1,R[2]=8,那么开始就把第二个点加入了一号位置,但是此时1号点还没有放,所以应该按照拓扑序为第一关键字,L为第二关键字,加点。

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cstring>
  4. #include<cmath>
  5. #include<iostream>
  6. #include<cctype>
  7. #include<set>
  8. #include<vector>
  9. #include<queue>
  10. #include<map>
  11. #define fi(s) freopen(s,"r",stdin);
  12. #define fo(s) freopen(s,"w",stdout);
  13. using namespace std;
  14. typedef long long LL;
  15. char buf[100000],*_p1 = buf,*_p2 = buf;
  16. #define nc() (_p1==_p2&&(_p2=(_p1=buf)+fread(buf,1,100000,stdin),_p1==_p2) ? EOF :*_p1++)
  17. inline int read() {
  18. int x=0,f=1;char ch=nc();for(;!isdigit(ch);ch=nc())if(ch=='-')f=-1;
  19. for (;isdigit(ch);ch=nc())x=x*10+ch-'0';return x*f;
  20. }
  21. #define pa pair<int,int>
  22. #define mp make_pair
  23. const int N = 300005;
  24. struct Edge{
  25. int to, nxt;
  26. }e[1000005];
  27. int head[N], En;
  28. int deg[N], deg2[N], L[N], R[N], q[N], ans[N];
  29. int n, m;
  30. priority_queue< pa, vector< pa >, greater< pa > > q1, q2;
  31. void add_edge(int u,int v) {
  32. ++En; e[En].to = v; e[En].nxt = head[u]; head[u] = En;
  33. deg[v] ++, deg2[v] ++;
  34. }
  35. bool solve() {
  36. int H = 1, T = 0;
  37. for (int i = 1; i <= n; ++i) if (!deg2[i]) q[++T] = i;
  38. while (H <= T) {
  39. int u = q[H ++];
  40. for (int i = head[u]; i; i = e[i].nxt)
  41. if (!(--deg2[e[i].to])) q[++T] = e[i].to;
  42. }
  43. if (T < n) return 0; //因为有环所以没有遍历完所有的点
  44. for (int i = n; i >= 1; --i) {
  45. int u = q[i];
  46. for (int i = head[u]; i; i = e[i].nxt)
  47. R[u] = min(R[u], R[e[i].to] - 1);
  48. if (L[u] > R[u]) return 0;
  49. }
  50. for (int i = 1; i <= n; ++i) if (!deg[i]) q1.push(mp(L[i], i));
  51. for (int now = 1; now <= n; ++now) {
  52. while (!q1.empty() && q1.top().first <= now)
  53. q2.push(mp(R[q1.top().second], q1.top().second)), q1.pop();
  54. if (q2.empty()) return 0;
  55. int u = q2.top().second; q2.pop();
  56. ans[now] = u;
  57. if (R[u] < now) return 0;
  58. for (int i = head[u]; i; i = e[i].nxt) {
  59. if (!(--deg[e[i].to])) q1.push(mp(L[e[i].to], e[i].to));
  60. }
  61. }
  62. for (int i = 1; i <= n; ++i) printf("%d\n", ans[i]);
  63. return 1;
  64. }
  65. int main() {
  66. n = read(), m = read();
  67. for (int i = 1; i <= n; ++i) L[i] = read(), R[i] = read();
  68. for (int i = 1; i <= m; ++i) {
  69. int u = read(), v = read();
  70. add_edge(u, v);
  71. }
  72. if (!solve()) puts("-1");
  73. return 0;
  74. }

T2

小S决定送给小萌一个礼物。
这是一个特殊的礼物,它是一个集合,且集合所有的数的,所有数的
小S他有多少种不同的送礼方案呢。两个送礼方案不同当且仅当存在某个在一个方案中而不在另一个中。
答案对取模。

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cstring>
  4. #include<cmath>
  5. #include<iostream>
  6. #include<cctype>
  7. #include<set>
  8. #include<vector>
  9. #include<queue>
  10. #include<map>
  11. #define fi(s) freopen(s,"r",stdin);
  12. #define fo(s) freopen(s,"w",stdout);
  13. using namespace std;
  14. typedef long long LL;
  15. inline int read() {
  16. int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
  17. for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
  18. }
  19. const int N = 20;
  20. const int mod = 998244353;
  21. int p[N], cnt;
  22. LL Ans;
  23. void init(LL m) {
  24. for (int i = 2; 1ll * i * i <= m; ++i) {
  25. if (m % i) continue;
  26. cnt ++;
  27. while (m % i == 0) p[cnt] ++, m /= i;
  28. }
  29. if (m > 1) p[++cnt] = 1;
  30. }
  31. int ksm(int a,int b) {
  32. int res = 1;
  33. while (b) {
  34. if (b & 1) res = 1ll * res * a % mod;
  35. a = 1ll * a * a % mod;
  36. b >>= 1;
  37. }
  38. return res;
  39. }
  40. void dfs(int x,int c,int val) {
  41. if (x > cnt) {
  42. Ans += 1ll * (ksm(2, val) - 1 + mod) * c % mod;
  43. if (Ans >= mod) Ans -= mod;
  44. return ;
  45. }
  46. dfs(x + 1, c, 1ll * val * (p[x] + 1) % (mod - 1));
  47. dfs(x + 1, (-2ll * c % mod + mod) % mod, 1ll * val * p[x] % (mod - 1));
  48. if (p[x] > 1) dfs(x + 1, c, 1ll * val * (p[x] - 1) % (mod - 1));
  49. }
  50. int main() {
  51. LL m; cin >> m;
  52. init(m);
  53. dfs(1, 1, 1);
  54. cout << Ans;
  55. return 0;
  56. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注