首页 > 其他分享 >CF585F Digits of Number Pi 题解

CF585F Digits of Number Pi 题解

时间:2024-07-26 21:51:03浏览次数:8  
标签:Digits 子串 kMod int 题解 trie kMaxT Pi 10

Description

给定长度为 \(n\) 的数字串 \(s\) 和长度为 \(d\) 的不含前导零的数字串 \(x,y(x \le y)\)。

存在长度至少为 \(\left\lfloor\frac{d}{2}\right\rfloor\) 的子串是 \(s\) 的子串的数字串 \(t \in [x,y]\) 的数量。

\(n \le 10^3\),\(d \le 50\),答案对 \(10^9+7\) 取模。

Solution

先把 \(s\) 所有长度为 \(\left\lfloor\frac{d}{2}\right\rfloor\) 的子串拿出来,那么相当于要求这些子串必须在 \(t\) 里出现,考虑用总数减去没出现的数量。

考虑用 \([0,y]\) 的答案减去 \([0,x-1]\) 的答案,这样就只有上界了。

注意到这里是很多个字符串匹配一个串,考虑把 \(s\) 的这些子串加到 AC 自动机里,那么这些子串没在 \(t\) 里出现当且仅当从前往后扫 \(t\) 的每一个字符,每次让 \(cur\leftarrow trie_{cur,t_i}\),如果这里的 \(cur\) 每次都不在 \(s\) 子串对应的节点上就说明子串没在 \(t\) 里出现。

这样就可以 dp 了。设 \(f_{i,j,0/1}\) 表示 \(1\sim i-1\) 走到 \(j\),\(i\sim n\) 每次不走子串对应节点,后面有没有卡上界的限制的方案数。

转移就每次枚举 \(t_i\) 即可。

时间复杂度:\(O\left(|\Sigma|^2nd^2\right)\),\(|\Sigma|\) 为字符集大小。

Code

#include <bits/stdc++.h>

// #define int int64_t

const int kMaxN = 1e3 + 5, kMaxD = 55, kMaxT = kMaxN * kMaxD * 5, kMod = 1e9 + 7;

int n, d, tot;
int a[kMaxN], trie[kMaxT][10], fail[kMaxT], f[kMaxD][kMaxT][2];
bool tag[kMaxT], vis[kMaxD][kMaxT][2];
std::string s, L, R;

inline int add(int x, int y) { return (x + y >= kMod ? x + y - kMod : x + y); }
inline int sub(int x, int y) { return (x >= y ? x - y : x - y + kMod); }
inline void inc(int &x, int y) { (x += y) >= kMod ? x -= kMod : x; }
inline void dec(int &x, int y) { (x -= y) < 0 ? x += kMod : x; }

std::string sub(std::string s) {
  for (int i = d; i; --i) {
    if (s[i] != '0') {
      --s[i];
      for (int j = i + 1; j <= d; ++j) s[j] = '9';
      break;
    }
  }
  return s;
}

void ins(std::string s) {
  int cur = 0;
  for (auto c : s) {
    int k = c - '0';
    if (!trie[cur][k]) trie[cur][k] = ++tot;
    cur = trie[cur][k];
  }
  tag[cur] = 1;
}

void build() {
  std::queue<int> q;
  for (int i = 0; i < 10; ++i) {
    if (trie[0][i]) {
      q.emplace(trie[0][i]);
    }
  }
  for (; !q.empty();) {
    int u = q.front(); q.pop();
    for (int i = 0; i < 10; ++i) {
      if (trie[u][i]) {
        fail[trie[u][i]] = trie[fail[u]][i];
        q.emplace(trie[u][i]);
      } else {
        trie[u][i] = trie[fail[u]][i];
      }
    }
  }
}

int dfs(int x, int k, bool op) {
  if (x > d || tag[k]) return !tag[k];
  else if (vis[x][k][op]) return f[x][k][op];
  int ret = 0;
  for (int i = 0; i <= (op ? a[x] : 9); ++i) {
    inc(ret, dfs(x + 1, trie[k][i], op && (i == a[x])));
  }
  vis[x][k][op] = 1;
  return f[x][k][op] = ret;
}

int solve(std::string t) {
  for (int i = 1; i <= d; ++i) a[i] = t[i] - '0';
  int ans = 0;
  for (int i = 1; i <= d; ++i) ans = (10ll * ans + a[i]) % kMod;
  memset(f, 0, sizeof(f)), memset(vis, 0, sizeof(vis));
  return sub(ans, dfs(1, 0, 1));
}

void dickdreamer() {
  std::cin >> s >> L >> R;
  n = s.size(), d = L.size();
  s = " " + s, L = " " + L, R = " " + R;
  for (int i = 1; i <= n - (d / 2) + 1; ++i)
    ins(s.substr(i, d / 2));
  build();
  std::cout << sub(solve(R), solve(sub(L))) << '\n';
}

int32_t main() {
#ifdef ORZXKR
  freopen("in.txt", "r", stdin);
  freopen("out.txt", "w", stdout);
#endif
  std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
  int T = 1;
  // std::cin >> T;
  while (T--) dickdreamer();
  // std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";
  return 0;
}

标签:Digits,子串,kMod,int,题解,trie,kMaxT,Pi,10
From: https://www.cnblogs.com/Scarab/p/18326341

相关文章

  • Postman自定义插件全攻略:扩展你的API开发工具箱
    Postman自定义插件全攻略:扩展你的API开发工具箱Postman作为API开发的瑞士军刀,其强大的功能集已经为开发者所熟知。但你知道吗?Postman还允许开发者使用自定义插件来进一步扩展其功能。这些插件可以帮助自动化重复性任务、增强测试能力,甚至集成其他服务。本文将详细介绍如何......
  • 【小白记录深度学习】——物理信息神经网络(PINNs)
    本文的内容基于论文解读,解读的论文为Physics-InformedNeuralNetworksforShellStructures和RecentAdvancesandApplicationsofMachineLearninginExperimentalSolidMechanics:AReview什么是物理信息神经网络PINNs(Physics-informedNeuralNetworks,物理信息神......
  • 【Azure APIM】调用APIM的备份接口时候遇见InvalidParameters错误
    问题描述根据官方文档,可以调用RESTAPI来对APIM执行备份操作。要备份API管理服务,请发出以下HTTP请求:POSThttps://management.chinacloudapi.cn/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ApiManagement/service/{serviceN......
  • CF578E Walking! 题解
    Description给定一个长度为\(n\)的只包含L,R的字符串\(s\)。构造一个\(n\)排列\(p\)满足\(s[p_i]\nes[p_{i+1}](1\lei<n)\)。最小化\(p\)中\(p_i>p_{i+1}(1\lei<n)\)的数量。\(n\le10^5\),数据保证有解。Solution考虑把\(p\)中的每个极长连......
  • Android Compose 使用 照片选择器 Photo Picker
    从Android13(Tiramisu,API33)开始,官方提供了系统级图片选择器PhotoPicker。而且无需申请权限,只需几行代码即可轻松接入。效果如下图:在不支持PhotoPicker的低版本机型中,该库会自动调用ACTION_OPEN_DOCUMENT打开系统资源管理器进行选择,问题也不大。官方介绍and教程:Ph......
  • 小信小友逛庙会 题解
    题目id:9774题目描述小信与小友相约逛庙会。但是庙会人很多,他们走散了。庙会能表示成\(n×m\)的矩阵,小信在'\(C\)',小友在'\(D\)','\(.\)'表示能走,'#'表示店铺(也就是不能走)。每分钟,小信可以往\(8\)个方向移动一格,而小友可以移动一次或者两次,每次可以往\(4\)个方向(上下左右)移动一......
  • Postman中的API容错测试:构建健壮系统的秘诀
    Postman中的API容错测试:构建健壮系统的秘诀在当今的技术环境中,API的容错能力是衡量其健壮性的关键指标之一。容错能力指的是API在面对错误输入、系统故障或异常情况时,仍能正常工作或优雅地降级服务的能力。Postman作为一个强大的API测试工具,提供了多种功能来帮助测试人员验......
  • 开心消消乐 题解
    题目id:8578题目描述\(A\)酱最近在玩开心消消乐,由于是异次元的游戏,所以规则可能和地球上的有所不同。开心消消乐是一个在大圆环上进行的游戏,环上有若干个宝石,每颗宝石都有自己的积分,由于消消乐是一个三消游戏,我们每次可以挑选其中一个宝石消去,消去宝石的积分为他的积分和左右相......
  • CF1988F 较草题解
    \[\begin{aligned}&f_{i,j,k},g_{i,j,k}\to(i\text{permutation},j\text{premaxorsufmax},k(a[l]>a[l-1]))\\&\text{Initialize:}f_{1,1,0}=g_{1,1,0}=1\\&\text{Transferforf,g}\\&f_{i,j,k}=f_{i-1,j-1,k-1......
  • 参天大树 题解
    题目id:5602题目描述丛林中矗立着一棵参天大树,高度为\(y\)。大树\(2\simp\)高度处,每个位置都有一只蚱蜢。一只蚱蜢如果在\(x\)高度处,那么它可以跳到\(2x、3x、4x、......\)等任意一个\(x\)的倍数处。你想在\(2\simy\)高度范围内,找到一个尽可能高且不会有任何蚂蚱能跳到的位......