关于给数组赋值,一个函数为memset
,其在cplusplus.com中的描述如下:
void * memset ( void * ptr, int value, size_t num );
Sets the first num bytes of the block of memory pointed by ptr to the specified value (interpreted as an unsigned char
).
将 ptr 指向的内存块的前字节数设置为指定值(解释为 an unsigned char
)。
ptr
Pointer to the block of memory to fill. 指向要填充的内存块的指针。
value
Value to be set. The value is passed as an int
, but the function fills the block of memory using the unsigned char conversion of this value. 要设置的值。该值作为 an int
传递,但该函数使用此值的 unsigned char 转换填充内存块。
num 编号
Number of bytes to be set to the value. 要设置为该值的字节数。 size_t is an unsigned integral type. size_t 是无符号整型。
关于给数组赋值,一个函数为fill
,其在cplusplus.com中它的描述如下:
template <class ForwardIterator, class T> void fill (ForwardIterator first, ForwardIterator last, const T& val);
Assigns val to all the elements in the range [first,last)
.
将 val 分配给范围 [first,last)
中的所有元素。
Parameters 参数
first, last 第一个、最后一个
Forward iterators to the initial and final positions in a sequence of elements that support being assigned a value of type T. The range filled is [first,last)
, which contains all the elements between first and last, including the element pointed by first but not the element pointed by last. 将迭代器转发到支持为 type T 分配值的元素序列中的初始和最终位置。填充的范围是 [first,last),
它包含 first 和 last 之间的所有元素,包括 first 指向的元素,但不包括 last 指向的元素。
val
Value to assign to the elements in the filled range. 要分配给填充区域中元素的值。
// fill algorithm example
#include // std::cout
#include // std::fill
#include // std::vector
int main () {
std::vector<int> myvector (8); // myvector: 0 0 0 0 0 0 0 0
std::fill (myvector.begin(),myvector.begin()+4,5); // myvector: 5 5 5 5 0 0 0 0
std::fill (myvector.begin()+3,myvector.end()-2,8); // myvector: 5 5 5 8 8 8 0 0
std::cout << "myvector contains:";
for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
#include
using namespace std;
using LL = long long;
#define endl "\n"
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
vector<int> nums(5);
for(auto &u : nums) {
cin >> u;
}
int sum = 0;
for(int i = 0; i < 5; i ++) {
sum += nums[i] % 3;
nums[i] -= nums[i] % 3;
nums[(i + 4) % 5] += nums[i] / 3;
nums[(i + 1) % 5] += nums[i] / 3;
nums[i] /= 3;
}
for(auto &u : nums) {
cout << u << " ";
}
cout << endl;
cout << sum << endl;
return 0;
}
此处五个人围成一个圈,可以用取模运算。
关于对加法的理解,一个人的编号加上2就是前进两个人。例如编号为0的人加上2得到编号为2的人。总共有五个人, 所以加上五即为0+5=5,即又回到了自己的位置。若编号特别大则对5取模又可以将编号控制在0到4。
关于对减法的理解,一个人的编号减去1就是相当于加上了n-1个人。最后加上取模操作可将编号控制在0到4。
#include
using namespace std;
using LL = long long;
#define endl "\n"
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int _;
cin >> _;
int nums[31] = {0};
nums[1] = 1;
nums[2] = 1;
for(int i = 3; i <= 30; i ++) {
nums[i] = nums[i - 1] + nums[i - 2];
}
while(_ --) {
int x;
cin >> x;
cout << nums[x] << endl;
}
return 0;
}
对数组的理解:递推求解并存储答案。从微小的状态开始求取整个过程并用数组进行存储。每次计算出nums[i],即nums[i] = 计算的公式。
#include
using namespace std;
using LL = long long;
#define endl "\n"
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n;
cin >> n;
double fact[16] = {1};
double e = 1;
for(int i = 1; i <= n; i ++) {
fact[i] = i * fact[i - 1];
e += 1 / fact[i];
}
cout << fixed << setprecision(10) << e << endl;
return 0;
}
对数组的理解:和上面的方法相同,采用递推的方法求解阶乘并将其存储在数组中。
关于以下代码,是我学到的新方法:
#include
using namespace std;
using LL = long long;
#define endl "\n"
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n;
cin >> n;
double invfact[16] = {1}, e = 1;
for(int i = 1; i < 16; i ++) {
invfact[i] = invfact[i - 1] / i;
}
e += accumulate(invfact + 1, invfact + n + 1, 0.0);
cout << fixed << setprecision(10) << e << endl;
return 0;
}
其中的accumulate函数极其精妙。
cplusplus.com中的描述:
template <class InputIterator, class T> T accumulate (InputIterator first, InputIterator last, T init);
template <class InputIterator, class T, class BinaryOperation> T accumulate (InputIterator first, InputIterator last, T init, BinaryOperation binary_op);
Returns the result of accumulating all the values in the range [first,last)
to init.
返回将 [first,last)
范围内的所有值累加到 init
The default operation is to add the elements up, but a different operation can be specified as binary_op.
默认操作是将元素相加,但可以将不同的操作指定为 binary_op
first, last 第一个、最后一个
Input iterators to the initial and final positions in a sequence. The range used is [first,last)
, which contains all the elements between first and last, including the element pointed by first but not the element pointed by last.
将迭代器输入到序列中的初始和最终位置。使用的范围是 [first,last),
它包含 first 和 last 之间的所有元素,包括 first 指向的元素,但不包括 last 指向的元素。
init 初始化
Initial value for the accumulator.
累加器的初始值。
binary_op
Binary operation taking an element of type T as first argument and an element in the range as second, and which returns a value that can be assigned to type T.
将 type T 的元素作为第一个参数,将 range 中的元素作为第二个参数的二进制运算,并返回一个可分配给 type T 的值。
This can either be a function pointer or a function object.
这可以是函数指针或函数对象。
The operation shall not modify the elements passed as its arguments.
该操作不得修改作为其参数传递的元素。
#include
using namespace std;
using LL = long long;
#define endl "\n"
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n;
cin >> n;
vector<int> nums(n);
for(int i = 0; i < n; i ++) {
cin >> nums[i];
}
//reverse(nums.begin(), nums.end());
for(int i = 0, j = n - 1; i < j; i ++, j --) {
swap(nums[i], nums[j]);
}
for(int i = 0; i < n; i ++) {
cout << nums[i] << " ";
}
return 0;
}
着重体会函数reverse()和swap()的用法。
#include
using namespace std;
using LL = long long;
#define endl "\n"
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n;
cin >> n;
vector<int> nums(n + 1, 0);
for(int i = 2; i <= n; i ++) {
for(int j = i; j <= n; j += i) {
nums[j] = 1 - nums[j];
}
}
for(int i = 1; i <= n; i ++) {
if(!nums[i]) {
cout << i << " ";
}
}
cout << endl;
return 0;
}
启发:因为每次关掉的是i的倍数,所以只需要这样遍历即可:
for(int j = i; j <= n; j += i) {
}
#include
using namespace std;
using LL = long long;
#define endl "\n"
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n, m;
cin >> n >> m;
vector<vector<int>> nums(n, vector<int>(m));
int sum = 0;
for(int i = 0; i < n; i ++) {
for(int j = 0; j < m; j ++) {
cin >> nums[i][j];
}
}
for(int i = 0; i < n; i ++) {
for(int j = 0; j < m; j ++) {
if(!i || !j || i == n - 1 || j == m - 1) {
sum += nums[i][j];
}
}
}
cout << sum << endl;
return 0;
}
启发:可以采用这种写法以满足题意if(!i || !j || i == n - 1 || j == m - 1)
#include
using namespace std;
using LL = long long;
#define endl "\n"
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n, m;
cin >> n >> m;
vector<vector<int>> nums(n, vector<int>(m));
for(int i = 0; i < n; i ++) {
for(int j = 0; j < m; j ++) {
cin >> nums[i][j];
}
}
vector<vector<int>> res(m, vector<int>(n));
for(int i = 0; i < m; i ++) {
for(int j = 0; j < n; j ++) {
res[i][j] = nums[n - j - 1][i];
}
}
for(int i = 0; i < m; i ++) {
for(int j = 0; j < n; j ++) {
cout << res[i][j] << " ";
}
cout << endl;
}
return 0;
}
启发:在考虑矩阵是如何旋转的,我是这样思考的。
对于矩阵的变换,它顺时针旋转了90°
1 2 3 7 4 1
4 5 6 8 5 2
7 8 9 9 6 3
对于res[i][j]
, 我进行考虑它是如何转变的到的。在i = 0 且 j = 0时,我们发现他是由7变换得到;对于一整行来说,我们发现,第一行是由第一列变换得到。所以我猜想:res[i][j] = backup[][i]
(这句话的意思是:res数组的第i行是由backup的第i列变换得到,当i = 0时,就有res数组的第0行是由backup数组的第0列变换得到。显然它满足直观看出来的结论)。而考察其中一个数字,对数字1来说,它是由7变化得到,故可以猜想得到它由n - j - 1
变化得到。故得到了res[i][j] = backup[n - j - 1][i]
#include
using namespace std;
using LL = long long;
#define endl "\n"
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n, m;
cin >> n >> m;
vector<vector<double>> g(n, vector<double>(m));
for(auto& line : g) {
for(auto& x : line) {
cin >> x;
}
}
vector<vector<double>> res(n, vector<double>(m, -1));
for(int i = 0; i < n; i ++) {
for(int j = 0; j < m; j ++) {
if(i != 0 && i != n - 1 && j != 0 && j != m - 1) {
double sum = g[i][j] + g[i - 1][j] + g[i + 1][j] + g[i][j - 1] + g[i][j + 1];
res[i][j] = round(sum / 5);
} else {
res[i][j] = g[i][j];
}
}
}
for(auto& line : res) {
for(auto& x : line) {
cout << x << " ";
}
cout << endl;
}
return 0;
}
启发:四舍五入round()
;注意数据被污染。
数组的copymemcpy(b, a, sizeof(a))
将a数组copy至b数组。