zoukankan      html  css  js  c++  java
  • [SOJ #538]好数 [CC]FAVNUM(2019-8-6考试)

    题目大意:给定$n$个正整数,求$[l,r]$中第$k$小的”好数“。$l,rleqslant10^{18},nleqslant62$,出现的其他数均$leqslant10^{50}$

    好数定义为它至少包含这$n$个数中的一个

    题解:二分答案,数位$DP$+$AC$自动机上$DP$,求一个数是第几个好数可以见[文本生成器](https://www.cnblogs.com/Memory-of-winter/p/11305126.html)

    卡点:

    C++ Code:

    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    const int maxn = 20 * 1000;
    
    long long n, k, l, r;
    long long f[20][maxn];
    namespace AC {
    	int nxt[maxn][10], fail[maxn], idx = 1;
    	bool End[maxn];
    	void insert(std::string s) {
    		int p = 1;
    		for (char ch : s) {
    			if (nxt[p][ch & 15]) p = nxt[p][ch &15];
    			else p = nxt[p][ch & 15] = ++idx;
    		}
    		End[p] = true;
    	}
    	void build() {
    		std::queue<int> q;
    		for (int i = 0; i < 10; ++i)
    			if (nxt[1][i]) fail[nxt[1][i]] = 1, q.push(nxt[1][i]);
    			else nxt[1][i] = 1;
    		while (!q.empty()) {
    			int u = q.front(); q.pop();
    			for (int i = 0; i < 10; ++i)
    				if (nxt[u][i]) {
    					fail[nxt[u][i]] = nxt[fail[u]][i];
    					End[nxt[u][i]] |= End[fail[nxt[u][i]]];
    					q.push(nxt[u][i]);
    				} else nxt[u][i] = nxt[fail[u]][i];
    		}
    	}
    
    	int num[20], tot;
    	long long calc(int x, int lim, int lead, int p) {
    		if (!x) return lead;
    		long long F = f[x][p];
    		if (~F && !lim && lead) return F;
    		F = 0;
    		for (int i = lim ? num[x] : 9, up = 1; ~i; --i, up = 0)
    			if (!End[nxt[p][i]])
    				F += calc(x - 1, lim && up, lead || i, nxt[p][i]);
    		if (~F && !lim && lead) f[x][p] = F;
    		return F;
    	}
    	long long solve(long long x) {
    		if (!x) return 0;
    		long long X = x;
    		tot = 0;
    		while (x) num[++tot] = x % 10, x /= 10;
    		return X - calc(tot, 1, 0, 1);
    	}
    	long long query(long long k, long long L, long long R) {
    		long long base = solve(L - 1), l = L, r = R, ans = L;
    		while (l <= r) {
    			long long mid = l + r >> 1, t = solve(mid) - base;
    			if (t >= k) r = mid - 1, ans = mid;
    			else l = mid + 1;
    		}
    		if (solve(ans) - base != k) return -1;
    		return ans;
    	}
    }
    
    int main() {
    	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
    	memset(f, -1, sizeof f);
    	std::cin >> l >> r >> k >> n;
    	for (int i = 0; i < n; ++i) {
    		static std::string s;
    		std::cin >> s;
    		AC::insert(s);
    	}
    	AC::build();
    	std::cout << AC::query(k, l, r) << '
    ';
    	return 0;
    }
    

      

  • 相关阅读:
    晒一下我的统一网站管理平台
    走向DBA[MSSQL篇] 从SQL语句的角度 提高数据库的访问性能
    XSS跨站脚本实例
    关于开源的一点看法
    晒一下我的监控系统
    走向DBA[MSSQL篇] 详解游标
    【linux+C】新征程 linux下C编程
    走向DBA[MSSQL篇] 针对大表 设计高效的存储过程【原理篇】 附最差性能sql语句进化过程客串
    晒一下我的web过滤器
    分享新出炉的微软派工具 你,值得拥有
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/11308834.html
Copyright © 2011-2022 走看看