A卡片(3181)
思路
1.将数字0-9分别存到数组中,并将其值设为2021。
2.从1开始遍历,若遍历的数字需要哪个数字,哪个数字对应于的数组中的值-1,直到数组中的元素<0就遍历结束。
代码
#include<stdio.h>
int main(){
int a[15];
for(int i=0; i<=9; i++)
a[i] = 2021;
int flag = 0;
int i;
for(i=1; flag==0; i++){
int temp = i;
while(temp > 0){
a[temp%10]--;
if(a[temp%10] < 0){
printf("%d",i-1);
flag = 1;
break;
}
temp /= 10;
}
}
return 0;
}
B直线(40257)
思路
1.存储直线的斜率与截距,用set(可自动去重)。
2.输出set的所存储的元素的个数+20+21(横线和竖线)。
#include<bits/stdc++.h>
using namespace std;
struct point{
int x; //横坐标
int y; //纵坐标
};
int main(){
vector<point> p; //存放所有点
for(int i=0; i<20; i++)
for(int j=0; j<21; j++)
p.push_back({i,j});
int len = p.size();
set<pair<double, double> > lines; //存放直线的斜率与截距
for(int i=0; i<len; i++){
for(int j=0; j<len; j++){
if (p[i].x != p[j].x && p[i].y != p[j].y){ //统计所有斜直线的情况
double k = (p[j].y - p[i].y) * 1.0 / (p[j].x - p[i].x);
double b = (p[j].y * (p[j].x - p[i].x) - (p[j].y - p[i].y) * p[j].x) * 1.0 / (p[j].x - p[i].x);
lines.insert(pair<double, double>(k,b));
}
}
}
cout << lines.size() + 20 + 21 << endl; //总线=斜线+横直线+竖直线
return 0;
}
C货物摆放(2430)
思路1
参考链接
1.问题转化为,将 2021041820210418分解为三个数abc的形式,有多少种拆分方式。
2.将2021041820210418分解,可得 2021041820210418 = 21 * 33 * 171 * 1311 * 28571 * 58823531 。
3.对于:2,17,131,2857,5882353,分配给a,b,c的方法共有35。
4.对于出现了三次的3,枚举出其所有的分配方式,共10种。
5.故总方法数为:35 * 10 = 2430。
代码
#include<bits/stdc++.h>
using namespace std;
int main(){
long long n = 2021041820210418;
vector<int> a;
for(long long int i=2; i<=n; i++){
if(n%i == 0){
int num = 0;
while(n % i == 0){
a.push_back(i);
n /= i;
num++;
}
}
}
for(int i=0; i<a.size(); i++)
cout<<a[i]<<' ';
//2 3 3 3 17 131 2857 5882353
cout<<endl;
cout<<pow(3,5)*10;
return 0;
}
思路2
参考链接
1.观察题目,最终的结果是数字6的全部约数,因此我们可以求出全部因数。
2.求出因数,写三个for循环,将因子中的数字 相乘,看其结果是否为 2021041820210418。
#include<bits/stdc++.h>
using namespace std;
int main(){
long long int n = 2021041820210418;
vector<long long> fac;
for(long long i = 1; i * i <= n; i++){
if (n % i == 0) {
fac.push_back(i);
if(n/i != i)
fac.push_back(n / i);
}
}
int ans = 0;
int sz = fac.size();
for(int i = 0; i < sz; i++)
for(int j = 0; j < sz; j++)
for(int k = 0; k < sz; k++)
if(fac[i] * fac[j] * fac[k] == n)
ans++;
cout << ans << endl;
return 0;
}
D路径(10266837)
思路
首先我用弗洛伊德没跑出结果,是我太菜了。
参考的别人的dp。参考地址
代码
#include<bits/stdc++.h>
#define MAX 999999999
int path[2100] = {0};
using namespace std;
//两点之间的路径
long long gcd(int a, int b) {
if (a % b == 0)
return b;
return gcd(b, a % b);
}
long long lcm(int a, int b) {
return a * b / gcd(a, b);
}
int main(){
memset(path, 0, sizeof(path));
for(int i=2; i<=2021; i++)
path[i] = MAX;
for(int i=1; i<=2021; i++){
for(int j=i+1; j<=i+21; j++){
long long edge = lcm(i,j);
if(path[j] > path[i] + edge)
path[j] = path[i] + edge;
}
}
cout << path[2021] << endl;
return 0;
}
E回路计数
试题F:砝码称重