学习目标:
巩固算法笔记第五章
学习内容:
2021寒假集训Part 1
学习时间:
2021-9-17
学习产出:
题单点这里
补题弱鸡
1 P2181 对角线
#include<iostream>
using namespace std;
int main(){
unsigned long long n, ans;
scanf("%lld",&n);
ans = n * (n - 1) / 2 * (n - 2) / 3 * (n - 3) /4;
printf("%lld",ans);
return 0;
}
知道公式就很简单啦
交点个数为 n * (n-1) * (n-2) * (n-3) / 24
防止爆了 优化为 n * (n-1) / 2 * (n-2) / 3 * (n-3) / 4
因为一个交点由两条线四个点形成 所以只需要在n变形的n个点中找四个点(四边形) 即组合数 C n 4;
另外提醒自己再记一下
n变形对角线个数 n * (n - 3)/ 2
2 P2043 质因子分解
#include<iostream>
using namespace std;
const int maxn = 10010;
int prime[maxn], pNum = 0;
bool p[maxn] = {0};
void find_prime(){//埃氏筛法得素数表
for(int i = 2; i < maxn; i++){
if(p[i] == false){
prime[pNum++] = i;
for(int j = i + i; j < maxn; j += i){
p[j] = true;
}
}
}
}
int f(int n, int p){//求!n中可分解多少质因子p
int ans = 0;
if(n < p){
ans = 0;
}else{
while(n / p){
ans += n / p;
n /= p;
}
}
return ans;
}
int main(){
int n;
scanf("%d", &n);
find_prime();
for(int i = 0; i < pNum; i++){
if(f(n, prime[i]) != 0){
printf("%d %d\n", prime[i], f(n, prime[i]));
}
}
return 0;
}
典型的埃筛以及 求!n中可分解多少质因子p的公式
!n中有(n/p + n/p/p + …)个质因子p
3 P1036 [NOIP2002 普及组] 选数
#include<iostream>
using namespace std;
int n, k;
int a[25] = {0};
bool isprime(int q){
if(q <= 1){
return false;
}
for(int i = 2; i * i <= q; i++){
if(q % i == 0){
return false;
}
}
return true;
}
int select(int len, int sum_already, int begin, int end){//len为已经选择的个数 sum_already为目前选取的数的和 begin和end分别为可以选择的区间
if(len == k){
return isprime(sum_already);
}
int sum = 0;
for(int i = begin; i <= end; i++){
sum += select(len + 1, sum_already + a[i], i + 1, end);
}
return sum;
}
int main(){
scanf("%d%d", &n, &k);
for(int i = 0; i < n; i++){
scanf("%d", &a[i]);
}
printf("%d",select(0, 0, 0, n - 1));
return 0;
}
递归的使用
4 P1451 求细胞数量
还没写完
5 P2807 三角形计数
#include<iostream>
using namespace std;
int ans(int n){
if(n % 2 == 1){
return (n + 1) * (2 * n * n + 3 * n - 1) / 8;
}else{
return n * (n + 2) * (2 * n + 1) / 8;
}
}
int main(){
int n, k;
scanf("%d", &n);
while(n--){
scanf("%d", &k);
printf("%d\n", ans(k));
}
return 0;
}
典型的数学问题
大佬详解传送门
6 P3811 【模板】乘法逆元
#include<iostream>
using namespace std;
typedef long long ll;
ll binary_pow(ll a, ll b, ll m){
if(b == 0){
return 1;
}
if(b % 2 == 1){
return a * binary_pow(a, b - 1, m) % m;
}else{
ll temp = binary_pow(a, b / 2, m);
return temp * temp % m;
}
}
int main(){
ll n, p;
scanf("%lld%lld", &n, &p);
for(ll i = 1; i <= n; i++){
printf("%lld\n",binary_pow(i, p - 2, p));
}
return 0;
}
7 P1887 乘积最大3
#include<iostream>
using namespace std;
int main(){
int n, m;
scanf("%d %d", &n, &m);
for(int i = 0; i < m - n % m; i++){
printf("%d ", n / m);
}
for(int i = 0; i < n % m; i++){
printf("%d ", n / m + 1);
}
return 0;
}
考察思维 当所有数最接近时且相差不大于一时可求解
8 P4942 小凯的数字
#include<iostream>
using namespace std;
typedef long long ll;
ll q, l, r;//根据题意所设
//假设 5 ~ 27 即 5678910111213。。。252627
//写成 5 * 10^N 6 * 10^N ... 27 * 10^N
// 10^N % 9 恒为 1
// 可以写成 5%9 6%9 .。。。 27%9
// 易知 结果为 0 ~ 8 循环 而 0 加到 8 和为 36 即省去中间以9为周期的所有数
ll ans(ll begin, ll end){
ll sum = 0;
if(end - begin < 10){
for(ll i = begin; i <= end; i++){
sum += i % 9;
}
}else{
for(ll i = 0; i <= (end - begin) % 9; i++){
sum += (begin + i) % 9;
}
}
return sum % 9;
}
int main(){
scanf("%lld", &q);
while(q--){
scanf("%lld %lld", &l, &r);
printf("%d\n", ans(l, r));
}
return 0;
}
思维题