喜迎暑假多校联赛第一场


一、qcjj想玩 I wanna


传送门


不会不会,太难了,我是菜鸡


二、云哥教你学数学!


传送门

1.思路


拿到这题一看到n ≤ ≤ 1 0 9 10^9 109,要求f(n),那肯定是矩阵快速幂的活了。
f ( x ) = 2 f ( x − 1 ) + 3 f ( x − 2 ) f(x)=2f(x-1)+3f(x-2) f(x)=2f(x1)+3f(x2)
做过斐波拉契的矩阵快速幂的就能很快推出矩阵了,这个问题的矩阵就是
K = ( 3 2 1 0 ) K= \begin{gathered} \begin{pmatrix} 3 & 2 \\ 1 & 0 \end{pmatrix} \end{gathered} K=(3120)
所以最重要的一步还是求出f(1)和f(2),比赛时想破脑袋竟然没想到暴力bfs求,草率了!!!!!只需要暴力2,3,5,到1e31的时候就行。哎,还是太拉跨了。将暴力得到的符合条件的值放入set中,最后找出第a个和第b个即可。记得用__int128。

2.参考代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll M = 1e9 + 7;
void print(__int128 x)
{
	if (!x) return;
	if (x < 0) putchar('-'), x = -x;
	print(x / 10);
	putchar(x % 10 + '0');
}
struct Matrix
{
	ll m[10][10];
	Matrix()
	{
		memset(m, 0, sizeof(m));
	}
};
ll ksc(ll a, ll b)
{
	ll ans = 0;
	while (b)
	{
		if (b & 1)ans = (ans + a) % M;
		a = (a + a) % M;
		b >>= 1;
	}
	return ans;
}
Matrix Multi(Matrix a, Matrix b)
{
	Matrix res;
	for (int i = 1; i <= 2; i++)
		for (int j = 1; j <= 2; j++)
			for (int k = 1; k <= 2; k++)
				res.m[i][j] = (res.m[i][j] + ksc(a.m[i][k], b.m[k][j])) % M;
	return res;
}
Matrix fastm(Matrix a, ll n)
{
	Matrix res;
	for (int i = 1; i <= 2; i++)
		res.m[i][i] = 1;
	while (n)
	{
		if (n & 1)res = Multi(res, a);
		a = Multi(a, a);
		n >>= 1;
	}
	return res;
}
set<__int128>ss;
void dfs(__int128 x)
{
	if (x > 1e31 || ss.count(x) != 0)return;
	ss.insert(x);
	dfs(x * 2);
	dfs(x * 3);
	dfs(x * 5);
}
int main() {

	dfs(1);
	ll a, b, n;
	scanf("%lld%lld%lld", &a, &b, &n);
	Matrix k;
	__int128 suma, sumb;
	int flag = 1;
	for (auto it : ss)
	{
		if (flag == a)suma = it;
		if (flag == b)sumb = it;
		flag++;
		if (sumb != 0)break;
	}
	k.m[1][1] = 2;
	k.m[1][2] = 3;
	k.m[2][1] = 1;
	k.m[2][2] = 0;
	if (n == 1)
	{
		print(suma);
	}
	else
	{
		k = fastm(k, n - 2);
		__int128 res = (sumb % M * k.m[1][1] + suma % M * k.m[1][2]) % M;
		print(res);
	}

}



三、纳米兔子


传送门

1.思路


没得思路,就是找规律,通过枚举前8种情况就行。我通过JAVA程序进行打表,得到了1到8代兔子数量积尾数0个数为1,2,4,8,15,25,35,35到了这不就有手就行了。

2.参考代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll sum[] = { 0,1,2,4,8,15,25,35,35 };
int main()
{
	ll n, m;
	while (~scanf("%lld%lld", &n, &m))
	{
		printf("%lld\n", n * sum[m]);
	}
}



四、纳米猫猫


传送门

1.思路


一样的没得思路,单纯就是找规律。

2.参考代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 123456;
int mod;
char s[N], b[N];
ll fastpower(ll x, ll y) {
	ll ans = 1;
	while (y)
	{
		if (y & 1) {
			ans = (ans * x) % mod;
			y--;
		}
		y /= 2;
		x = x * x % mod;
	}
	return ans;
}
ll quickmod(ll a, char b[], int len)
{
	ll ans = 1;
	while (len > 0) {
		if (b[len - 1] != '0') {
			int s = b[len - 1] - '0';
			ans = ans * fastpower(a, s) % mod;
		}
		a = fastpower(a, 10) % mod;
		len--;
	}
	return ans;
}
int main() {
	int a;
	cin >> a >> s >> mod;
	int len = strlen(s);
	int i = len - 1;
	while (s[i] == '0') {
		s[i] = '9'; i--;
	}
	s[i]--;
	i = 0;
	while (s[i] == '0')i++;
	for (int j = 0; s[i]; i++)b[j++] = s[i];
	len = strlen(b);
	if (mod == 1)cout << 0 << endl;
	else
		printf("%d\n", quickmod(a, b, len));
	return 0;
}



五、二巧板


传送门

1.思路


签到题,就是求两个三角形的面积之和。

2.参考代码

#include<bits/stdc++.h>
using namespace std;
const double PI = acos(-1.0);
const double eps = 1e-8;
int sgn(double x)
{
	if (fabs(x) < eps)return 0;
	else return x < 0 ? -1 : 1;
}
struct Point {
	double x, y;
	Point() {}
	Point(double x, double y) :x(x), y(y) {}
	Point operator + (Point B) { return Point(x + B.x, y + B.y); }
	Point operator - (Point B) { return Point(x - B.x, y - B.y); }
	Point operator * (double k) { return Point(x * k, y * k); }
	Point operator / (double k) { return Point(x / k, y / k); }
};
double Cross(Point A, Point B)//叉积
{
	return A.x * B.y - A.y * B.x;
}
double Area(Point A, Point B, Point C)//三角形面积*2
{
	return Cross(B - A, C - A);
}
int main()
{
	Point A, B, C, A1, B1, C1;
	scanf("%lf%lf%lf%lf%lf%lf", &A.x, &A.y, &B.x, &B.y, &C.x, &C.y);
	scanf("%lf%lf%lf%lf%lf%lf", &A1.x, &A1.y, &B1.x, &B1.y, &C1.x, &C1.y);
	double ans = fabs(Area(A, B, C) / 2) + fabs(Area(A1, B1, C1) / 2);
	printf("%.2lf\n", ans);
}



六、日常诈骗签到题


传送门

1.思路


看到这题,就想起了第一届河北工业大学程序设计竞赛校赛(同步赛)的J题,题面相似,而且那题也是差不多很简单,拿到这题我也没往难的程度想,最后发现答案竟然是

∑ i = 1 n i \displaystyle\sum_{i=1}^{n} i i=1ni,然后运用等差数列求和公式轻松A掉。

赛后自己还是手动推了一下,因为数学能力有限还是没能推到这个答案,但是却发现了一种新的思路—欧拉函数+整除分块
∑ i = 1 n ∑ j = 1 i ∑ d = 1 j n i μ ( d ) [ d ∣ i ] [ d ∣ j ] \displaystyle\sum_{i=1}^{n} \displaystyle\sum_{j=1}^{i}\displaystyle\sum_{d=1}^{j}\frac{n}{i} μ(d)[d∣i][d∣j] i=1nj=1id=1jinμ(d)[di][dj]
= ∑ i = 1 n n i ∑ j = 1 i ∑ d = 1 j μ ( d ) [ d ∣ g c d ( i , j ) ] =\displaystyle\sum_{i=1}^{n}\frac{n}{i} \displaystyle\sum_{j=1}^{i}\displaystyle\sum_{d=1}^{j} μ(d)[d|gcd(i,j)] =i=1ninj=1id=1jμ(d)[dgcd(i,j)]
= ∑ i = 1 n n i ∑ j = 1 i [ g c d ( i , j ) = = 1 ] =\displaystyle\sum_{i=1}^{n}\frac{n}{i} \displaystyle\sum_{j=1}^{i}[gcd(i,j)==1] =i=1ninj=1i[gcd(i,j)==1]
= ∑ i = 1 n n i φ ( i ) =\displaystyle\sum_{i=1}^{n}\frac{n}{i}φ(i) =i=1ninφ(i)

这不就整除分块+欧拉函数也能AC了嘛!!!!

2.参考代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll M = 1e9 + 7;
int main()
{
	int t;
	scanf("%d", &t);
	while (t--)
	{
		ll x;
		scanf("%lld", &x);
		ll xx = (x * x + x) / 2;
		xx %= M;
		printf("%lld\n", xx);
	}
}
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1e6 + 10;
const ll M = 1e9 + 7;
ll sum[maxn];
ll prime[maxn];
bool vis[maxn];
int cnt;
void Prime()
{
	sum[1] = 1;
	for (int i = 2; i < maxn; i++)
	{
		if (vis[i] == false)
		{
			prime[cnt++] = i;
			sum[i] = i - 1;
		}
		for (int j = 0; prime[j] * i < maxn; j++)
		{
			vis[prime[j] * i] = true;
			if (i % prime[j] == 0)
			{
				sum[prime[j] * i] = sum[i] * prime[j] % M;
				break;
			}
			else sum[prime[j] * i] = sum[i] * (prime[j] - 1) % M;
		}
	}
	for (int i = 1; i < maxn; i++)
		sum[i] = (sum[i - 1] + sum[i]) % M;
}
int main()
{
	Prime();
	int t;
	scanf("%d", &t);
	while (t--)
	{
		ll n;
		scanf("%lld", &n);
		ll ans = 0;
		for (ll l = 1, r; l <= n; l = r + 1)
		{
			r = min(n, n / (n / l));
			ans = (ans + (sum[r] - sum[l - 1]) * (n / l) % M) % M;
		}
		
		printf("%lld\n", ans);
	}
}



七、jzgg,云哥,沙烬巨巨为什么这么强


传送门

1.思路


题面吓死人,其实比较简单,只需要将输入的字符串进行一下简单处理,求出它要消耗的能量值,然后用区间DP模板或者放入优先队列即可解决。 在处理字符串时,难点在于求出它将前导0消除后的最长上升子序列长度,但是也是套模板即可。

2.参考代码


直接套用区间DP板子:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll inf = 0x3f3f3f3f;
const int maxn = 2e3 + 10;
ll a[maxn];
int n;
int dp1[maxn];
ll dp[maxn][maxn];
ll sum[maxn];
ll LAS(string s)
{
	memset(dp1, 0, sizeof(dp1));
	int x = 0;
	while (x < s.length() && s[x] == '0')x++;
	vector<ll>v; v.push_back(0);
	for (int i = x; i < s.length(); i++)
		v.push_back(s[i] - '0');
	int ans = s[x];
	ans *= (v.size() - 1);
	ll len = 0;
	for (int i = 1; i < v.size(); i++)
	{
		if (v[i] > dp1[len] || len == 0)dp1[++len] = v[i];
		else
		{
			int l = 1, r = len;
			while (l < r)
			{
				int mid = (l + r) >> 1;
				if (dp1[mid] >= v[i])r = mid;
				else l = mid + 1;
			}
			dp1[l] = v[i];
		}
	}
	ans *= len;
	return ans;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	memset(dp, inf, sizeof(dp));
	for (int i = 1; i <= n; i++)
	{
		string s;
		cin >> s;
		a[i] = LAS(s);
		sum[i] = sum[i - 1] + a[i];
		dp[i][i] = 0;
	}
	for (int len = 1; len <= n; len++)
	{
		for (int j = 1; j + len <= n + 1; j++)
		{
			int ends = j + len - 1;
			for (int i = j; i < ends; i++)
			{
				dp[j][ends] = min(dp[j][ends], dp[j][i] + dp[i + 1][ends] + sum[ends] - sum[j - 1]);
			}
		}
	}
	cout << dp[1][n] << endl;
}

用优先队列每次对两个最小值进行操作,然后求出它们对答案的贡献即可:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2e3 + 10;
int n;
int dp1[maxn];
ll LAS(string s)
{
	memset(dp1, 0, sizeof(dp1));
	int x = 0;
	while (x < s.length() && s[x] == '0')x++;
	vector<ll>v; v.push_back(0);
	for (int i = x; i < s.length(); i++)
		v.push_back(s[i] - '0');
	int ans = s[x];
	ans *= (v.size() - 1);
	ll len = 0;
	for (int i = 1; i < v.size(); i++)
	{
		if (v[i] > dp1[len] || len == 0)dp1[++len] = v[i];
		else
		{
			int l = 1, r = len;
			while (l < r)
			{
				int mid = (l + r) >> 1;
				if (dp1[mid] >= v[i])r = mid;
				else l = mid + 1;
			}
			dp1[l] = v[i];
		}
	}
	ans *= len;
	return ans;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	priority_queue<ll, vector<ll>, greater<ll>> q;
	for (int i = 1; i <= n; i++)
	{
		string s;
		cin >> s;
		q.push(LAS(s));
	}
	ll ans = 0;
	while (q.size() >= 2)
	{
        ll sum=0;
		sum += q.top();
		q.pop();
		sum += q.top();
		q.pop();
		q.push(sum);
        ans+=sum;
	}
	cout << ans << endl;
}



八、呜米喵想要成为爱抖露!


传送门

1.思路


脑瘫最小生成树,签到题,只需要在输入边权值的时候判断权值是否为质数,当为质数时将边权值改为0即可,然后直接套板子则可A掉。

2.参考代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2e5 + 10;
const int N = 1e7 + 10;
ll s[maxn];
ll prime[N];
bool vis[N];
int cnt;
struct edge {
	ll l, r;
	ll val;
}a[maxn];
void Prime()
{
	for (int i = 2; i < N; i++)
	{
		if (vis[i] == false) prime[cnt++] = i;
		for (int j = 0; i * prime[j] < N; j++)
		{
			vis[i * prime[j]] = true;
			if (i % prime[j] == 0) break;
		}
	}
}
bool cmp(edge x, edge y)
{
	return x.val < y.val;
}
void init()
{
	for (int i = 1; i < maxn; i++)
		s[i] = i;
}
int find(int x)
{
	if (s[x] != x)s[x] = find(s[x]);
	return s[x];
}
int main()
{
	Prime();
	ll n,m,k;
	init();
	scanf("%lld%lld", &n, &m);
	scanf("%lld", &k);
	for (int i = 1; i <= m; i++)
	{
		ll l, r;
		ll val;
		scanf("%lld%lld%lld", &l, &r, &val);
		if (!vis[val])val = 0;
		a[i] = { l,r,val };
	}
	int ans = 0;
	int flag = 0;
	sort(a + 1, a + 1 + m, cmp);
	for (int i = 1; i <= m; i++)
	{
		int xx, yy;
		xx = find(a[i].l);
		yy = find(a[i].r);
		if (xx != yy)
		{
			flag++;
			s[xx] = s[yy];
			ans += a[i].val;
		}
		if (flag == n - 1)break;
        if(ans>=k)break;
	}
	if (flag == n - 1 && ans < k)printf("wmmxycwdjdwdlnljbzwtskirakira\n");
	else printf("wmmxycwdjdwdlnljbzwtsfljt\n");
}



九、MeUmy的海底捞抽奖旅程


传送门


不会,我是fw!



十、MeUmy吃海底捞


传送门


不会,不会,还是不会!



十一、VUP Information Management Favorite


传送门


老模拟题了,但是太复杂了,搞人心态呀。



十二、来签到


传送门

1.思路

思路就是水群!!!!!!!!!!

2.参考代码

B
A
AB
ACD
ABD
A
BD
D
BCD
A


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值