牛客小白月赛77

(0条未读通知) 牛客小白月赛77_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com)

小Why的循环置换

分析:

牛客小白月赛77_第1张图片

题目理解:这里连成环相当于拿一个数其对应下标的位置则为数的位置将其连成环,需要递增则相当于需要自环 

牛客小白月赛77_第2张图片

每操作一次就会多出来一个自环相当于此时的m就会+

代码:

#include
using namespace std;
int n, m;
int main()
{
	cin >> n >> m;
	cout << n - m;
	return 0;
}

小Why的商品归位

分析:

此题可以进行模拟,将当前商品的所在货架和应在货架统计出来,循环货架,统计开始在当前货架的商品,这些商品是需要加到购物车中的,当然如果说这里的商品本身就是最终位置将其减去即可。统计需要挪动商品的最大值,将其上取整(mx - 1) / k + 1即可计算出次数

代码:

#include
using namespace std;
const int N = 1000005;
int n, m, k, s, e, res, mx, st[N], ed[N];
int main()
{
	cin >> n >> m >> k;
	for(int i = 1; i <= m; i ++)
	{
		cin >> s >> e;
		st[s] ++;
		ed[e] ++;
	}
	for(int i = 1; i <= n; i ++)
	{
		res += st[i];
		res -= ed[i];
		mx = max(mx, res);
	}
	cout << (mx - 1) / k + 1;
	return 0; 
}

小Why的密码锁

分析:

使用substr会超时,故使用字符串哈希,但是需要记录上一次哈希到相同子串的位置来避免重复

比如这样一组输入

7 4 2

1231231

显然正确输出是0,但是如果不对每一次哈希到这个串的位置标记就会导致记录了不该记录的子串

例如 1231 会记录两次

那我们就可以记录第一次1231的位置,如果下一次1231出现,和前一次1231出现的位置重叠了,那么肯定就不合法了

因为第一个1231出现后被删去就只剩下231 就没有第二个1231了

字符串hash模板:

牛客小白月赛77_第3张图片

#include
using namespace std;
typedef unsigned long long ULL;
const int N = 1e6 + 10;
const int P = 131;
ULL p[N], h[N];
char s[N];
map cnt;
map last;
int n, m, k, ans;
//预处理hash函数的前缀和
void init()
{
	p[0] = 1;
	for(int i = 1; i <= n; i ++)
	{
		p[i] = p[i - 1] * P;
		h[i] = h[i - 1] * P + s[i];	
	}	
} 
//计算s[l~r]的hash值
ULL get(int l, int r)
{
	return h[r] - h[l - 1] * p[r - l + 1];
} 
int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin >> n >> m >> k >> s + 1;
	init();
	for(int i = 1; i <= n; i ++)
	{
		if(i + m - 1 > n)break;
		ULL x = get(i, i + m - 1);
		if(last[x] + m - 1 >= i && last[x])continue;
		cnt[x] ++;
		last[x] = i;
	}
	for(auto i : cnt)
	{
		if(i.second == k)ans ++;
	}
	cout << ans;
	return 0;
}

小Why的数论测试

分析:

由于题目所给数据可以观察用简单bfs无法通过,由于a * a这样计算可能会超范围,所以从b开始每次开根号即可,开根,除二,以及减一

牛客小白月赛77_第4张图片

解释:

eg.13: 需要执行 -1,然后 / 2,代码中的 + 1相当于/ 2的操作,然后用z.x - y - y算出多的呢部分需要执行的操作,如这里知道了需要执行-1操作,因为13 - 6 - 6 = 1

代码:

#include
using namespace std;
typedef long long ll;
struct node
{
	ll x, y;
};
void solve()
{
	ll ans = 1e12;
	ll a, b;
	cin >> a >> b;
	if(a == b)ans = 0;
	else
	{
		queue q;
		q.push({b, 0});
		while(!q.empty())
		{
			node z = q.front();
			q.pop();
			ll x = sqrt(z.x),
			y = z.x >> 1;
			if(z.x <= a)continue;
			if(x >= a)
			{
				ll res = z.y + z.x - x * x + 1;
				if(x == a)ans = min(ans, res);
				else q.push({x, res});
			}
			if(y >= a)
			{
				ll res = z.y + z.x - y - y + 1;
				if(y == a)ans = min(ans, res);
				else q.push({y, res});
			}
			if(y < a)
			{
				ll res = z.y + z.x - a;
				ans = min(ans, res);
			}
		}
	}	
	cout << ans << '\n';
}
int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	ll t;
	cin >> t;
	while(t --)
	{
		solve();
	}
	return 0;
}

你可能感兴趣的:(算法)