Skip to content

Commit 95a0ed8

Browse files
committed
docs: 完成洛谷题解
1 parent 54eeb66 commit 95a0ed8

File tree

1 file changed

+314
-6
lines changed
  • content/blog/soft-enginering-exam

1 file changed

+314
-6
lines changed

content/blog/soft-enginering-exam/index.md

Lines changed: 314 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1870,19 +1870,327 @@ for i in range(0,500+1,50):
18701870
print(res[i:i+50])
18711871
```
18721872

1873-
### 12. [P1249](https://www.luogu.com.cn/problem/P1249)
1873+
### 12. [P1249 最大乘积](https://www.luogu.com.cn/problem/P1249)
18741874

1875-
### 13. [P1012](https://www.luogu.com.cn/problem/P1012)
1875+
思路:高精度用`Python`,要想乘积大那么就要让数字均匀从`2+3+4+5+...`,然后剩余值再从后向前匀,有个特殊情况就是剩余的数对于最后的数,那么我们就要给最后的数`+2`,剩下的数还是`+1`,比如:`2+3->8``3`但是只有两个数,所以我们必须把后面的`3+2`,然后`2+1`,最后得到`3+5=8`。还有就是`2+3=5`所以`4`以内直接输出本身即可
18761876

1877-
### 14. [P1923](https://www.luogu.com.cn/problem/P1923)
1877+
```python
1878+
import math
1879+
1880+
n = int(input())
1881+
1882+
if n <= 4:
1883+
print(n)
1884+
print(n)
1885+
exit()
1886+
1887+
parts = []
1888+
current = 2
1889+
remaining = n
1890+
1891+
while remaining >= current:
1892+
parts.append(current)
1893+
remaining -= current
1894+
current += 1
1895+
1896+
if remaining > 0:
1897+
if remaining == parts[-1]:
1898+
parts[-1] += 1
1899+
remaining -= 1
1900+
1901+
for i in range(len(parts)-1, -1, -1):
1902+
if remaining <= 0:
1903+
break
1904+
parts[i] += 1
1905+
remaining -= 1
1906+
1907+
1908+
product = 1
1909+
for num in parts:
1910+
product *= num
1911+
1912+
1913+
print(" ".join(map(str, parts)))
1914+
print(product)
1915+
```
18781916

1879-
### 15. [P1116](https://www.luogu.com.cn/problem/P1116)
1917+
### 13. [P1012 拼数](https://www.luogu.com.cn/problem/P1012)
18801918

1881-
### 16. [P1068](https://www.luogu.com.cn/problem/P1068)
1919+
思路:我们把数存进字符串数组,然后以`a+b>b+a`比较,这样两数合并产生更大结果的数会被排序到前面,字符串长度一样的时候按照字典序比较,和正常比较数的结果是一样的,然后我们把排序结果直接输出就可以得到最大的数
1920+
1921+
```cpp
1922+
#include <bits/stdc++.h>
1923+
1924+
using namespace std;
1925+
using ll = long long;
1926+
1927+
int main()
1928+
{
1929+
int n;
1930+
cin >> n;
1931+
vector<string> nums(n);
1932+
for (auto& s:nums)
1933+
{
1934+
cin >> s;
1935+
}
1936+
1937+
sort(nums.begin(),nums.end(),
1938+
[](string a,string b)
1939+
{
1940+
return a+b>b+a;
1941+
});
1942+
1943+
for (auto& s:nums)
1944+
{
1945+
cout << s;
1946+
}
1947+
}
1948+
```
1949+
1950+
### 14. [P1923 求第 k 小的数](https://www.luogu.com.cn/problem/P1923)
1951+
1952+
思路:直接用`nth_element`,我们不是算法竞赛,能快就快.jpg,注意nth_element是一种排序方法,它保证指定位置左边一定小右边一定大,而且不保证顺序,比一般排序快,我们要获取第k大(从0计)的可以用`*(nums.begin()+k)`或者`nums[k]`,使用迭代器读取的时候别忘记加括号再解引用,不然会变成`*(nums.begin())+k`,注意这题输入量很大,所以要用`ios_base::sync_with_stdio(0)``cin.tie(nullptr)`来加速读取
1953+
1954+
```cpp
1955+
#include <bits/stdc++.h>
1956+
1957+
using namespace std;
1958+
using ll = long long;
1959+
1960+
int main()
1961+
{
1962+
ios_base::sync_with_stdio(0);
1963+
cin.tie(nullptr);
1964+
1965+
int n,k;
1966+
cin >> n >> k;
1967+
vector<ll> nums(n);
1968+
for (auto& i:nums)
1969+
{
1970+
cin >> i;
1971+
}
1972+
nth_element(nums.begin(),nums.begin()+k,nums.end());
1973+
cout << *(nums.begin()+k);
1974+
1975+
}
1976+
```
1977+
1978+
### 15. [P1116 车厢重组](https://www.luogu.com.cn/problem/P1116)
1979+
1980+
思路:仔细读一下题目,发现和冒泡排序的原理一模一样,所以这题其实问的是冒泡排序要交换几次,考的是基本功
1981+
1982+
```cpp
1983+
#include <bits/stdc++.h>
1984+
1985+
using namespace std;
1986+
using ll = long long;
1987+
1988+
int main()
1989+
{
1990+
int n;
1991+
cin >> n;
1992+
vector<int> nums(n);
1993+
for (auto& i:nums)
1994+
{
1995+
cin >> i;
1996+
}
1997+
1998+
int res=0;
1999+
for (int i=0;i<n-1;i++)
2000+
{
2001+
for (int j=0;j<n-1-i;j++)
2002+
{
2003+
if (nums[j]>nums[j+1])
2004+
{
2005+
swap(nums[j],nums[j+1]);
2006+
res++;
2007+
}
2008+
}
2009+
}
2010+
cout << res;
2011+
}
2012+
```
2013+
2014+
### 16. [P1068 分数线划定](https://www.luogu.com.cn/problem/P1068)
2015+
2016+
思路:先把参与者按照分数和ID排序,然后按照排名找到分数线,输出大于等于分数线的参与者
2017+
2018+
```cpp
2019+
#include <bits/stdc++.h>
2020+
2021+
using namespace std;
2022+
using ll = long long;
2023+
2024+
struct Att
2025+
{
2026+
int id;
2027+
int score;
2028+
};
2029+
2030+
int main()
2031+
{
2032+
int n,m;
2033+
cin >> n >> m;
2034+
vector<Att> atts(n);
2035+
for (auto& i:atts)
2036+
{
2037+
cin >> i.id >> i.score;
2038+
}
2039+
2040+
sort(atts.begin(),atts.end(),
2041+
[](Att& a,Att& b)
2042+
{
2043+
if (a.score!=b.score)
2044+
{
2045+
return a.score>b.score;
2046+
}
2047+
return a.id<b.id;
2048+
});
2049+
2050+
int pass_rank=floor(m*1.5);
2051+
int pass_score=atts[pass_rank-1].score;
2052+
int res=0;
2053+
for (auto &i:atts)
2054+
{
2055+
if (i.score<pass_score) break;
2056+
res++;
2057+
}
2058+
2059+
cout << pass_score << " " << res << '\n';
2060+
for (auto &i:atts)
2061+
{
2062+
if (i.score<pass_score) break;
2063+
printf("%04d %d\n",i.id,i.score);
2064+
}
2065+
}
2066+
```
18822067

18832068
### 17. [P1706](https://www.luogu.com.cn/problem/P1706)
18842069

1885-
### 18. [P2249](https://www.luogu.com.cn/problem/P2249)
2070+
思路1:用递归遍历所有位置的排列,使用`used`集合来标记每个使用过的数字
2071+
2072+
```cpp
2073+
#include <bits/stdc++.h>
2074+
2075+
using namespace std;
2076+
using ll = long long;
2077+
2078+
int n;
2079+
void dfs(int start,vector<int> nums,unordered_set<int> used)
2080+
{
2081+
if (nums.size()==n)
2082+
{
2083+
for (auto& i:nums)
2084+
{
2085+
printf("%5d",i);
2086+
}
2087+
cout << '\n';
2088+
return;
2089+
}
2090+
2091+
for (int i=1;i<=n;i++)
2092+
{
2093+
if (used.count(i)) continue;
2094+
2095+
nums.push_back(i);
2096+
used.insert(i);
2097+
dfs(i+1,nums,used);
2098+
used.erase(i);
2099+
nums.pop_back();
2100+
}
2101+
2102+
}
2103+
2104+
int main()
2105+
{
2106+
cin >> n;
2107+
vector<int> nums;
2108+
unordered_set<int> used;
2109+
dfs(1,nums,used);
2110+
}
2111+
```
2112+
2113+
思路2:使用`next_permutaion`输出所有组合,注意,`next_permutation`只能输出排序过的组合,按照字典序排列,没有排序过的话输出的组合会不完整
2114+
2115+
```cpp
2116+
#include <bits/stdc++.h>
2117+
2118+
using namespace std;
2119+
using ll = long long;
2120+
2121+
2122+
int main()
2123+
{
2124+
int n;
2125+
cin >> n;
2126+
vector<int> nums(n);
2127+
for (int i=1;i<=n;i++)
2128+
{
2129+
nums[i-1]=i;
2130+
}
2131+
2132+
do
2133+
{
2134+
for (auto& i:nums)
2135+
{
2136+
printf("%5d",i);
2137+
}
2138+
cout << '\n';
2139+
} while (next_permutation(nums.begin(),nums.end()));
2140+
2141+
}
2142+
```
2143+
2144+
### 18. [P2249 查找](https://www.luogu.com.cn/problem/P2249)
2145+
2146+
思路:用二分查找`lower_bound`,注意使用这个方法必须是排过序的,返回值是第一个大于等于所给数的迭代器
2147+
2148+
|方法|作用|返回值|
2149+
|:--:|:--:|:--:|
2150+
|binary_search|查找元素是否存在|bool(是否存在)|
2151+
|lower_bound|第一个大于等于所给数的位置|迭代器|
2152+
|upper_bound|第一个大于所给数的位置|迭代器|
2153+
2154+
> `upper_bound - lower_bound`还可以查找元素出现次数
2155+
2156+
```cpp
2157+
#include <bits/stdc++.h>
2158+
2159+
using namespace std;
2160+
using ll = long long;
2161+
2162+
2163+
int main()
2164+
{
2165+
ios_base::sync_with_stdio(0);
2166+
cin.tie(nullptr);
2167+
2168+
int m,q;
2169+
cin >> m >> q;
2170+
vector<int> nums(m);
2171+
for (auto& i:nums)
2172+
{
2173+
cin >> i;
2174+
}
2175+
sort(nums.begin(),nums.end());
2176+
string sep;
2177+
while (q--)
2178+
{
2179+
int k;
2180+
cin >> k;
2181+
auto it=lower_bound(nums.begin(),nums.end(),k);
2182+
if (it==nums.end()||*it!=k)
2183+
{
2184+
cout << sep << -1;
2185+
}
2186+
else
2187+
{
2188+
cout << sep << it-nums.begin()+1;
2189+
}
2190+
sep=" ";
2191+
}
2192+
}
2193+
```
18862194

18872195
## 真题
18882196

0 commit comments

Comments
 (0)