G-Day01 10.2 总结

#A.学习求余

题目传送门

首先看到是一道像数学题的题,那么考虑暴力打表。

打表后发现规律为:

  • nn 为奇数是,答案为 $\lfloor \dfrac{n}{2} \rfloor \times \lceil \dfrac{n}{2} \rceil$。
  • nn 为偶数时,答案为 (n÷2+1)×(n÷21)(n \div2 + 1) \times (n \div 2 - 1)

考虑证明。

有一个小学知识:两个和一定的数,差越小,积越大;并且和较小的数乘起来的最大乘积肯定比和较大的数乘起来的最大乘积小。

那么当 k>n÷2k > n \div 2 时,q=nmodk=nkq=n \bmod k=n-k

kn÷2k \le n \div 2q+k<nq+k<n

那么想要让乘积最大,则 kk 必须比 n÷2n \div 2(向下取整)大,而为了使 kkqq 差值最小,我们将 kk 设为 n2=n÷2+1\lceil \dfrac{n}{2} \rceil=n \div 2+1,则 qq 就是 nkn-k,此时乘积最大。

Code:

#include <bits/stdc++.h>
#define int long long
using namespace std;
int n;

void Fio (string iofile)
{
	string ifl = iofile + ".in", ofl = iofile + ".out";
	freopen (ifl.c_str (), "r", stdin);
	freopen (ofl.c_str (), "w", stdout); 
}

signed main ()
{
	Fio ("mod");
	cin >> n;
	cout << (n / 2 - (!(n & 1))) * (n / 2 + 1);
	return 0;
}

感受与学习:数学题多打表,细心找规律。

错误原因:无。


#B.提取数字

简单字符串处理题,用数位分离即可。

每次遇到字母,就顺着它一直遍历下去并更改下标直到遇到数字,而遇到数字则运用数位分离提取数字直到遇到字母,注意边界问题即可。

Code:

#include <bits/stdc++.h>
#define int long long
using namespace std;
int n, ans;
string s;

void Fio (string iofile)
{
	string ifl = iofile + ".in", ofl = iofile + ".out";
	freopen (ifl.c_str (), "r", stdin);
	freopen (ofl.c_str (), "w", stdout); 
}

signed main ()
{
	Fio ("number");
    cin >> n >> s;
	for (int i = 0; i < s.size (); i ++)
	{
		if (isdigit (s[i]))
		{
			int j = i, res = 0;
			while (isdigit (s[j]) && j < s.size ())
				res = res * 10 + s[j ++] - '0';
			i = j - 1, ans += res + 5;
		}
		else
		{
			while (islower (s[i]) && i < s.size ())
				i ++;
			i --;
		}
	}
	cout << ans;
	return 0;
}

感受与学习:字符串处理时,多注意边界问题。

错误原因:无。

剩下的实在不会就先不写了