123789456ye

已AFO

3.10考试总结

话说最近感觉越来越喜欢压行了qaq

A 概率好题

题意:51nod 1667
题解:咕咕咕

B lyk与gcd

题意:51nod 1678
题解:容斥
所求等于所有的和减去不与 i 互质的和
直接将 i 质因数分解,不用管次数(比如说4算了贡献,那这份贡献肯定2里面也有,所以不用算4)
然后容斥出这个和
比如\(val(60)=val(2)+val(3)+val(5)-val(2,3)-val(2,5)-val(3,5)+val(2,3,5)\)
然后就维护一个\(val\)数组,使得\(val[i]\)表示以所有质因数含有 i 作为下标的原数组的和
于是\(val(2,3)==val[6]\)

#include<bits/stdc++.h>
using namespace std;
template<typename T>
inline void read(T& x)
{
	x = 0; char c = getchar();
	while (!isdigit(c)) c = getchar();
	while (isdigit(c)) x = x * 10 + c - '0', c = getchar();
}
#define maxn 100005
#define int long long
int a[maxn], n, q;
vector<int> ve;
int val[maxn], sum;
inline void fac(int x)
{
	ve.clear();
	for (int i = 2; i * i <= x; ++i)
		if (x % i == 0)
		{
			ve.push_back(i);
			while (x % i == 0) x /= i;
		}
	if (x != 1) ve.push_back(x);
}
inline int query(int x)
{
	fac(x);
	int ans = 0, len = ve.size();
	for (int i = 1; i < (1 << len); ++i)
	{
		int cnt = 0, tp = 1;
		for (int j = 0; j < len; ++j)
			if (i & (1 << j)) ++cnt, tp *= ve[j];
		if (cnt & 1) ans += val[tp];
		else ans -= val[tp];
	}
	return ans;
}
inline void update(int pos, int v)
{
	sum += v - a[pos];
	for (int i = 1; i * i <= pos; ++i)
		if (pos % i == 0)
		{
			val[i] += v - a[pos];
			if (i * i != pos) val[pos / i] += v - a[pos];
		}
	a[pos] = v;
}
signed main()
{
	read(n), read(q);
	for (int i = 1; i <= n; ++i) read(a[i]), sum += a[i];
	for (int i = 1; i <= n; ++i)
		for (int j = 1; i * j <= n; ++j) val[i] += a[i * j];
	for (int i = 1, op, x, y; i <= q; ++i)
	{
		read(op), read(x);
		if (op == 1) read(y), update(x, y);
		else printf("%lld\n", sum - query(x));
	}
	return 0;
}

C 高楼和棋子

题意:51nod 1306
题解:dp
\(dp[i][j]\)表示有 i 个棋子,试 j 次最多能试出来的最高楼层
于是每一个询问二分一下即可
注意1或2个棋子时要特判(因为状态数是\(\sqrt[i]{10^{18}}\)这个级别的)
注意要开vector,以及inf要开大一点

#include<bits/stdc++.h>
using namespace std;
template<typename T>
inline void read(T& x)
{
	x = 0; char c = getchar();
	while (!isdigit(c)) c = getchar();
	while (isdigit(c)) x = x * 10 + c - '0', c = getchar();
}
#define ll long long
#define maxnum 2000000
ll n, m;
vector<ll> dp[65];
int main()
{
	int T; read(T);
	for (int i = 0; i <= maxnum; ++i)
		dp[0].push_back(0);
	for (int i = 1; i <= 64; ++i)
	{
		dp[i].push_back(0);
		for (int j = 1; j <= maxnum; ++j)
		{
			dp[i].push_back(dp[i - 1][j - 1] + dp[i][j - 1] + 1);
			if (dp[i][j] > 1e18) break;
		}
	}
	while (T--)
	{
		read(n), read(m);
		if (m == 1) printf("%lld\n", n);
		else if (m == 2)
		{
			long long tp = sqrt(2 * n);
			if (tp * (tp + 1) < 2 * n) ++tp;
			printf("%lld\n", tp);
		}
		else printf("%d\n", (int)(lower_bound(dp[m].begin(), dp[m].end(), n) - dp[m].begin()));
	}
	return 0;
}

D 大大走格子

题意:51nod 1468
题解:容斥+dp
把障碍点按y排序,依次从前面递推,容斥一下即可

#include<bits/stdc++.h>
using namespace std;
inline void read(int& x)
{
	x = 0; char c = getchar();
	while (!isdigit(c)) c = getchar();
	while (isdigit(c)) x = x * 10 + c - '0', c = getchar();
}
#define maxn 200005
#define P 1000000007
#define ll long long
struct Node
{
	int x, y;
	bool operator < (const Node& p) const { if (y != p.y) return y < p.y; return x < p.x; }
}node[maxn];
ll ans[maxn], fac[maxn], inv[maxn];
inline ll qpow(ll x, ll y)
{
	ll ans = 1;
	while (y) { if (y & 1) ans = ans * x % P; x = x * x % P; y >>= 1; }
	return ans;
}
inline ll C(int x, int y) { return fac[x] * inv[y] % P * inv[x - y] % P; }
int main()
{
	int h, w, n, tp;
	read(h), read(w), read(n), tp = max(h, w) * 2;
	fac[0] = inv[0] = 1;
	for (int i = 1; i <= n; ++i)
		read(node[i].x), read(node[i].y), --node[i].x, --node[i].y;
	for (int i = 1; i <= tp; ++i) fac[i] = fac[i - 1] * i % P;
	inv[tp] = qpow(fac[tp], P - 2);
	for (int i = tp - 1; i; --i) inv[i] = inv[i + 1] * (i + 1) % P;
	node[++n] = { h - 1,w - 1 };
	sort(node + 1, node + n + 1);
	for (int i = 1; i <= n; ++i)
	{
#define X node[i].x
#define Y node[i].y
		ans[i] = C(X + Y, X);//从起点走到这个点
		for (int j = 1; j < i; ++j)//从前一个障碍点走到这个点
		{
			if (node[j].x > X || node[j].y > Y) continue;
			ans[i] = ans[i] - ans[j] * C(X - node[j].x + Y - node[j].y, X - node[j].x) % P;
			ans[i] %= P;
		}
		ans[i] = (ans[i] + P) % P;
	}
	printf("%lld\n", ans[n]);
	return 0;
}
posted @ 2020-03-15 10:52  123789456ye  阅读(89)  评论(0编辑  收藏  举报