[关闭]
@2368860385 2020-11-07T03:05:55.000000Z 字数 3509 阅读 171

day9

正睿停课


真的是啥都不会啊。。。
居然啥都想不出,还码不出。。。

T1

题目链接
https://www.zhihu.com/question/36252015/answer/66946594

填完1后的方案,剩下的填法都是一样的。
所以,求出合法的填1的方案 / 总的填1的方案 * 数独的总的方案。就是答案。
求合法的1的方案。
1、状压:
f[i][sta]记录到第i行,那些列位置没有填。可以三行三行的转移,所以i只有012就行了。前三行的状态一定是001|010|100类似的,就是每三位一个1。然后枚举下一个三行的哪些列是1。发现f[0/1/2]的合法的状态互不干扰(即f[0]只有每三位内一个1,f[1]只有每三位内2个1,f[2]只有每三位内3个1的方案是合法的),于是可以压掉一维。
2、搜索:
记录每个块内有没有,这一列有没有。每一行一行的转移,由于去掉很多状态,复杂度还是挺小的。
总的填1的方案数:求一下全0的数独。
数独的总方案数:用样例解一下?百度?

  1. 输入:
  2. 1
  3. 101101010
  4. 010000100
  5. 100100100
  6. 001001000
  7. 111011100
  8. 100100100
  9. 111010100
  10. 010101011
  11. 101101010
  12. 输出:
  13. 915672442
  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. char a[N][N];
  22. int vis[N], B[N];
  23. int sta1 = 46656, ista1 = 549081465, tot = 719935075, Ans;
  24. int ksm(int a,int b) {
  25. int res = 1;
  26. while (b) {
  27. if (b & 1) res = 1ll * res * a % mod;
  28. a = 1ll * a * a % mod;
  29. b >>= 1;
  30. }
  31. return res;
  32. }
  33. int getblock(int x,int y) {
  34. if (x <= 3) {
  35. return (y - 1) / 3 + 1;
  36. }
  37. if (x >= 4 && x <= 6) {
  38. return 3 + (y - 1) / 3 + 1;
  39. }
  40. return 6 + (y - 1) / 3 + 1;
  41. }
  42. void dfs(int x) {
  43. if (x == 10) { Ans ++; return ; }
  44. for (int i = 1; i <= 9; ++i) {
  45. if (a[x][i] == '1') continue;
  46. if (vis[i]) continue;
  47. int k = getblock(x, i);
  48. if (B[k]) continue;
  49. vis[i] = B[k] = true;
  50. dfs(x + 1);
  51. vis[i] = B[k] = false;
  52. }
  53. }
  54. void solve() {
  55. for (int i = 1; i <= 9; ++i) scanf("%s", a[i] + 1);
  56. Ans = 0;
  57. dfs(1);
  58. printf("%lld\n", 1ll * Ans * ista1 % mod * tot % mod);
  59. }
  60. int main() {
  61. // 191 / sta1 * tot = 915672442
  62. // int t1 = ksm(191, mod - 2);
  63. // cout << 1ll * 915672442 * t1 % mod * sta1 % mod; // tot
  64. for (int T = read(); T --; ) solve();
  65. return 0;
  66. }

T2

题目链接
每个点当然还是越早到越好,即使到了等红绿灯。所以直接求一下最短路即可,过程中求出每条边的权值。

  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. #define pa pair<LL,int>
  20. #define mp make_pair
  21. const int N = 500005;
  22. const LL INF = 1e18;
  23. struct Edge{
  24. int to, w, k, l, r, nxt;
  25. Edge() { }
  26. Edge(int _to, int _w, int _k, int _l, int _r, int _nxt) {
  27. to = _to, w = _w, k = _k, l = _l, r = _r, nxt = _nxt;
  28. }
  29. }e[2000005];
  30. int head[N], En, n;
  31. LL dis[N];
  32. bool vis[N];
  33. priority_queue< pa > q;
  34. LL Calc(int len, int now, int k, int l, int r) {
  35. LL ans = 0; int x = r - l + 1, y = k - x; // x走的时间,y等待的时间
  36. if (now <= l) ans += l - now; // 先到达时刻L处
  37. else if (now > l && now <= r) {
  38. if (r - now + 1 >= len) return len;
  39. ans += r - now + 1 + y; len -= r - now + 1;
  40. }
  41. else if (now > r) ans += k - now + l; // k - r + l!!!
  42. ans += len; // 一定要走的
  43. ans += y * ((len - 1) / x); // 等待的时间
  44. return ans;
  45. }
  46. void Dijkstra() {
  47. for (int i = 1; i <= n; ++i)
  48. vis[i] = false, dis[i] = INF;
  49. dis[1] = 0;
  50. q.push(mp(0, 1));
  51. while (!q.empty()) {
  52. pa now = q.top(); q.pop();
  53. int u = now.second;
  54. if (vis[u]) continue;
  55. vis[u] = true;
  56. for (int i = head[u]; i; i = e[i].nxt) {
  57. int v = e[i].to;
  58. LL w = Calc(e[i].w, dis[u] % e[i].k, e[i].k, e[i].l, e[i].r);
  59. if (dis[v] > dis[u] + w) {
  60. dis[v] = dis[u] + w;
  61. q.push(mp(-dis[v], v));
  62. }
  63. }
  64. }
  65. for (int i = 1; i <= n; ++i)
  66. printf("%lld\n", dis[i]);
  67. }
  68. int main() {
  69. n = read();int m = read();
  70. for (int i = 1; i <= m; ++i) {
  71. int u = read(), v = read(), w = read(), k = read(), l = read(), r = read();
  72. ++En; e[En] = Edge(v, w, k, l, r, head[u]); head[u] = En;
  73. ++En; e[En] = Edge(u, w, k, l, r, head[v]); head[v] = En;
  74. }
  75. Dijkstra();
  76. return 0;
  77. }
  78. //LL Calc(int len, int now, int k, int l, int r) {
  79. // LL ans=0;
  80. // if (now <= r && now >= l) {
  81. // if (r - now + 1 >= len) return len;
  82. // ans += r - now + 1; len -= r - now + 1; now = r + 1;
  83. // }
  84. // if (now > r) ans += k - now;
  85. // else ans -= now;
  86. //
  87. // int x = r - l + 1;
  88. // ans += 1ll * (len - 1) / x * k;
  89. // len = (len - 1) % x + 1;
  90. // ans += l + len;
  91. // return ans;
  92. //}
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注