提交 afd09fe6 编写于 作者: 每日一练社区's avatar 每日一练社区

update algorithm exercises

上级 0af3a237
......@@ -3,4 +3,5 @@
.DS_Store
__pycache__
*.pyc
*.zip
\ No newline at end of file
*.zip
help.py
# skill_tree_java
# skill_tree_algorithm
## 初始化
......@@ -43,9 +43,7 @@ pip install -r requirement.txt
{
// ...
"children": [
// TODO ...
],
"children": [],
}
```
......@@ -59,7 +57,12 @@ pip install -r requirement.txt
{
// ...
"export": [
// TODO ...
{
"file": "solution.c",
"variants": null,
"depends": []
},
// ...
]
}
```
......@@ -71,13 +74,17 @@ pip install -r requirement.txt
## `知识节点` 的导出习题选项配置编辑
首先,在知识节点下增加一个习题代码,例如在 `data/1.算法初阶/1.蓝桥杯/7段码` 下增加一个`HelloWorld.java`代码:
首先,在知识节点下增加一个习题代码,例如在 `data/1.算法初阶/1.蓝桥杯/7段码` 下增加一个`solution.c`代码:
```c
// TODO
#include <stdio.h>
int main(int argc, char** argv){
printf("Hello,Wrold!");
return 0;
}
```
其次,增加一个同名的选项配置文件`HelloWorld.json`,目前有两种配置规则
其次,增加一个同名的选项配置文件`solution.json`,目前有两种配置规则
**单行替换规则**
......@@ -88,7 +95,11 @@ pip install -r requirement.txt
```json
{
// TODO
"one_line": {
"printf": ["print"],
"return 0;": ["return 0"],
"(\"Hello,Wrold!\")": [" \"Hello,Wrold!\""]
}
}
```
......@@ -96,7 +107,11 @@ pip install -r requirement.txt
```c
// 变种代码1
// TODO
#include <stdio.h>
int main(int argc, char** argv){
print("Hello,Wrold!");
return 0;
}
```
```c
......@@ -110,7 +125,11 @@ int main(int argc, char** argv){
```c
// 变种代码3
// TODO
#include <stdio.h>
int main(int argc, char** argv){
print "Hello,Wrold!";
return 0
}
```
这些变种代码将会作为技能树该知识点该代码选择题的选项。
......@@ -124,7 +143,18 @@ int main(int argc, char** argv){
```json
{
// TODO
"multiline": [
{
"printf": "print"
},
{
"int main(int argc, char** argv){" : "int main(char** argv){",
"return 0;" : "return 0",
},
{
"#include <stdio.h>": ""
}
]
}
```
......@@ -132,17 +162,28 @@ int main(int argc, char** argv){
```c
// 变种代码1
// TODO
#include <stdio.h>
int main(int argc, char** argv){
print("Hello,Wrold!");
return 0;
}
```
```c
// 变种代码2, 注意第2组替换规则,包含了两行替换
// TODO
#include <stdio.h>
int main(char** argv){
print("Hello,Wrold!");
return 0
}
```
```c
// 变种代码3
// TODO
int main(int argc, char** argv){
print("Hello,Wrold!");
return 0;
}
```
## 技能树合成
......
#### 题目描述
小蓝要用七段码数码管来表示一种特殊的文字。
![七段码](https://img-blog.csdnimg.cn/2020110916441977.png#pic_left)
上图给出了七段码数码管的一个图示,数码管中一共有 7 段可以发光的二极管,分别标记为 a, b, c, d, e, f, g。
小蓝要选择一部分二极管(至少要有一个)发光来表达字符。在设计字符的表达时,要求所有发光的二极管是连成一片的。
* 例如:b 发光,其他二极管不发光可以用来表达一种字符。
* 例如:c 发光,其他二极管不发光可以用来表达一种字符。
这种方案与上一行的方案可以用来表示不同的字符,尽管看上去比较相似。
* 例如:a, b, c, d, e 发光,f, g 不发光可以用来表达一种字符。
* 例如:b, f 发光,其他二极管不发光则不能用来表达一种字符,因为发光的二极管没有连成一片。
请问,小蓝可以用七段码数码管表达多少种不同的字符?
\ No newline at end of file
#include<iostream>
using namespace std;
int use[10];
int ans, e[10][10], father[10];
void init()
{
//连边建图
//a b c d e f g
//1 2 3 4 5 6 7
e[1][2] = e[1][6] = 1;
e[2][1] = e[2][7] = e[2][3] = 1;
e[3][2] = e[3][4] = e[3][7] = 1;
e[4][3] = e[4][5] = 1;
e[5][4] = e[5][6] = e[5][7] = 1;
e[6][1] = e[6][5] = e[6][7] = 1;
}
int find(int a)//并查集
{
if (father[a] == a)
return a;
father[a] = find(father[a]);
return father[a];
}
//深度遍历
void dfs(int d)
{
if (d > 7)
{
for (int i = 1; i <= 7; i++)
{
father[i] = i;
}
for (int i = 1; i < 8; i++)
{
for (int j = 1; j < 8; j++)
{
if (e[i][j] == 1 && use[i] && use[j])
{
int fx = find(i);
int fy = find(j);
if (fx != fy)
{
father[fx] = fy;
}
}
}
}
int k = 0;
for (int i = 1; i < 8; i++)
{
if (use[i] && father[i] == i)
{
k++;
}
}
if (k == 1)
{
ans++;
}
return;
}
use[d] = 1;
dfs(d + 1);
use[d] = 0;
dfs(d + 1);
}
int main()
{
init();
dfs(1);
cout << ans;
return 0;
}
public class Main {
public static int N = 10;
public static int e[][] = new int[N][N];// 存储二极管相邻的信息
public static int f[] = new int[N];// 并查集
public static int ans = 0;
public static boolean st[] = new boolean[N];// true表示发光
public static void init() {
e[1][2] = e[1][6] = 1;// 表示相邻
e[2][1] = e[2][7] = e[2][3] = 1;
e[3][2] = e[3][7] = e[3][4] = 1;
e[4][3] = e[4][5] = 1;
e[5][7] = e[5][6] = e[5][4] = 1;
e[6][5] = e[6][7] = e[6][1] = 1;
e[7][2] = e[7][3] = e[7][5] = e[7][6] = 1;
}
public static int find(int u) {
if (f[u] == u)
return u;
f[u] = find(f[u]);
return f[u];
}
public static void dfs(int d) {// 1-7
if (d > 7) {
// 终止条件
for (int i = 1; i <= 7; i++) {// 并查集初始化
f[i] = i;
}
for (int i = 1; i <= 7; i++) {
for (int j = 1; j <= 7; j++) {
if (e[i][j] == 1 && st[i] == true && st[j] == true) {// 把所有发光且相邻的二极管合并
int fx = find(i), fy = find(j);
if (fx != fy) {
f[fx] = fy;// 合并
}
}
}
}
int k = 0;// 表示产生的集合的个数
for (int i = 1; i <= 7; i++) {
if (st[i] && f[i] == i)
k++;
}
if (k == 1)
ans++;// 只产生一个集合,说明所有的发光二极管是连成一片的
return;
}
st[d] = true;
dfs(d + 1);
st[d] = false;
dfs(d + 1);
}
public static void main(String[] args) {
init();
dfs(1);
System.out.println(ans);
}
}
观察如下的算式:
```
9213 x 85674 = 789314562
```
左边的乘数和被乘数正好用到了1~9的所有数字,每个1次。
而乘积恰好也是用到了1~9的所有数字,并且每个1次。
请你借助计算机的强大计算能力,找出满足如上要求的9数算式一共有多少个?
注意:
1. 总数目包含题目给出的那个示例。
2. 乘数和被乘数交换后作为同一方案来看待。
\ No newline at end of file
#include<bits/stdc++.h>
using namespace std;
int bei[10];//备用
map<long long,int>mp;
int main()
{
int a[9]={1,2,3,4,5,6,7,8,9};
int res=0;
do
{
for(int i=1;i<9;i++)
{
memset(bei,0,sizeof(bei));//分配空间
long long int ans,left=0,right=0,t=0,x=0,y=0;
for(int j=0;j<=i;j++)
{
left=left*10+a[j];
}
x=left;
x=x*10;
for(int k=i+1;k<9;k++)
{
right=right*10+a[k];
x=x*10+a[k];
}
y=right;
y=y*10;
for(int j=0;j<=i;j++)
y=y*10+a[j];
ans=left*right;
long long int ff=ans;
while(ans>0)
{
int x=ans%10;
ans=ans/10;
if(bei[x]==0&&x!=0)
{
bei[x]=1;
t++;
}
}
if(t==9&&mp.count(x)==0&&mp.count(y)==0)
{
res++;
mp[x]=1;
mp[y]=1;
}
}
}while(next_permutation(a,a+9));//全排列
cout<<res<<endl;
return 0;
}
import java.util.*;
public class Main {
static int[] a = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
static int ans;
public static void main(String[] args) {
f(0);
System.out.println(ans / 2);
}
// 全排列
private static void f(int k) {
// 全排列终点
if (k == a.length) {
// 处理该种排列下所有的乘法可能
for (int i = 1; i < a.length; i++) {
int x1 = a2i(0, i);
int x2 = a2i(i, a.length);
// 如果乘积也包含了九个数字,ans++
if (check(x1 * x2)) {
ans++; // 这里没有考虑x1和x2交换顺序的情况,所以最后输出时要除以2
}
}
}
// 全排列
for (int i = k; i < a.length; i++) {
int t = a[i];
a[i] = a[k];
a[k] = t;
f(k + 1);
t = a[i];
a[i] = a[k];
a[k] = t;
}
}
// 判断x是否是一个包含九个数字的数
private static boolean check(int x) {
String s = x + "";
if (s.length() != 9 || s.indexOf('0') > -1) {
return false;
}
Set<Character> set = new HashSet<Character>();
for (int i = 0; i < s.length(); i++) {
set.add(s.charAt(i));
}
if (set.size() == 9) {
return true;
}
return false;
}
// 将a数组[begin,end)转换为整数
private static int a2i(int begin, int end) {
int res = a[begin];
for (int i = begin + 1; i < end; i++) {
res *= 10;
res += a[i];
}
return res;
}
}
#### 题目描述
众所周知,小葱同学擅长计算,尤其擅长计算一个数是否是另外一个数的倍数。但小葱只擅长两个数的情况,当有很多个数之后就会比较苦恼。现在小葱给了你 n 个数,希望你从这 n 个数中找到三个数,使得这三个数的和是 K 的倍数,且这个和最大。数据保证一定有解。
#### 输入格式
从标准输入读入数据。
第一行包括 2 个正整数 n, K。
第二行 n 个正整数,代表给定的 n 个数。
#### 输出格式
输出到标准输出。
输出一行一个整数代表所求的和。
#### 样例输入
```
4 3
1 2 3 4
```
#### 样例输出
```
9
```
#### 样例解释
```
选择2、3、4。
```
\ No newline at end of file
#include<bits/stdc++.h>
#include<string>
#include<queue>
#include<set>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAX 1000000000
using namespace std;
int n,k,a[100010];
int b[4];
int flag=0;
void dfs(int a[],int n,int s){
if(flag==1) return;
if(s==4){
int sum=b[1]+b[2]+b[3];
if(sum%k==0){
flag=1;
cout<<sum<<endl;
}
return;
}
for(int i=1;i<=n;i++){
if(a[i]<a[s-1]){
b[s]=a[i];
dfs(a,n,s+1);
}
}
}
int main(){
cin>>n>>k;
a[0]=MAX;
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+n+1);
reverse(a+1,a+n+1);
dfs(a,n,1);
return 0;
}
import java.util.Scanner;
public class DFS {
static int max = -1; // 记录最大值
static int n, k;
static int[] num = new int[100010];
static int[] mark = new int[4]; // 记录每一步存储的数字
static boolean[] flag = new boolean[100010]; // 给num一个标记位 是否被使用过
static Scanner sc = new Scanner(System.in);
public static void main(String[] args) {
n = sc.nextInt();
k = sc.nextInt();
for (int i = 0; i < n; i++) {
num[i] = sc.nextInt();
}
dfs(0);
System.out.println(max);
}
// 使用深搜
public static void dfs(int step) {
// 判断结束条件
if (step == 3) {
int temp = mark[0] + mark[1] + mark[2];
if (temp % k == 0) {
max = Math.max(max, temp);
return;
}
}
for (int i = 0; i < n; i++) {
if (!flag[i]) { // 如果i还没有被记录过
flag[i] = true; // 给 这个数字设置标志位
mark[step] = num[i]; // 在mark中存储 这一位数字
dfs(step + 1);
flag[i] = false; // 循环结束 释放标记位
}
}
}
}
#### 问题描述
给定正整数 n, 求 1^8 + 2^8 +···+ n^8 mod 123456789 。其中 mod 表示取余。
#### 输入格式
输入的第一行包含一个整数 n。
#### 输出格式
输出一行,包含一个整数,表示答案。
#### 样例输入
```
2
```
#### 样例输出
```
257
```
#### 样例输入
```
987654
```
#### 样例输出
```
43636805
```
#### 评测用例规模与约定
对于 20% 的评测用例,1≤n≤20。
对于 60% 的评测用例,1≤n≤1000。
对于所有评测用例,1≤n≤1000000。
\ No newline at end of file
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int mod=123456789;
Scanner s = new Scanner(System.in);
int n=s.nextInt();long result=0;
for(long i=1;i<=n;i++){//遍历1~n
long temp=1;
for(int j=1;j<=4;j++){//对每一个 i 进行八次乘方,四次循环,每次循环里面计算一次平方
temp =(temp*((i*i) %mod))%mod; //计算平方并取模,防止溢出 }
result=(result+temp)%mod;//把每一次 i 循环得到的八次方结果汇总到变量 result 中。
}
System.out.println(result);//打印输出 resualt
}
}
{
"node_id": "569d5e11c4fc5de7844053d9a733c5e8",
"keywords": [],
"children": [],
"export": []
}
\ No newline at end of file
有一群海盗(不多于20人),在船上比拼酒量。过程如下:打开一瓶酒,所有在场的人平分喝下,有几个人倒下了。再打开一瓶酒平分,又有倒下的,
再次重复......
直到开了第4瓶酒,坐着的已经所剩无几,海盗船长也在其中。当第4瓶酒平分喝下后,大家都倒下了。
等船长醒来,发现海盗船搁浅了。他在航海日志中写到:“......昨天,我正好喝了一瓶.......奉劝大家,开船不喝酒,喝酒别开船......”
请你根据这些信息,推断开始有多少人,每一轮喝下来还剩多少人。
如果有多个可能的答案,请列出所有答案,每个答案占一行。
格式是:人数,人数,...
例如,有一种可能是:```20,5,4,2,0```
#include<cstdio>
#include<iostream>
using namespace std;
int d, a1[4];
int d1(int *a1) {
int sum = a1[0];
for (int i = 1; i < 4; i++) {
if (sum % a1[i] != 0) return i;
}
return 0;
}
int getS(int *a1) {
int sum = 0, ss = 1;
while(d1(a1) != 0) {
int index = d1(a1);
a1[0] = a1[0] * a1[index];
ss = a1[index];
}
for (int i = 1; i < 4; i++) {
sum += (a1[0]/a1[i]);
}
return sum+ss;
}
int main() {
for (int sum = 20; sum >= 1; sum--) {
for (int a = 1; a <= 20; a++) {
for (int b = 1; b <= 20; b++) {
for (int c = 1; c <= 20; c++) {
a1[0] = sum, a1[1] = a, a1[2] = b, a1[3] = c;
if (getS(a1) == a1[0] && a > b && b > c && sum > a) {
printf("%d, %d, %d, %d, 0\n", sum, a, b, c);
}
}
}
}
}
return 0;
}
\ No newline at end of file
public class Main {
public static void main(String[] args) {
for (int a = 20; a > 0; a--) {
for (int b = a - 1; b > 0; b--) {
for (int c = b - 1; c > 0; c--) {
for (int d = c - 1; d > 0; d--) {
int a1 = a * b * c;
int a2 = a * b * d;
int a3 = a * c * d;
int a4 = b * c * d;
int n = a * b * c * d;
if (a1 + a2 + a3 + a4 == n) {
System.out.println(a + "," + b + "," + c + "," + d);
}
}
}
}
}
}
}
#### 问题描述
观察这个数列:
1 3 0 2 -1 1 -2 ...
这个数列中后一项总是比前一项增加2或者减少3。
栋栋对这种数列很好奇,他想知道长度为 ```n``` 和为 ```s``` 而且后一项总是比前一项增加a或者减少b的整数数列可能有多少种呢?
#### 输入格式
  输入的第一行包含四个整数``` n s a b```,含义如前面说述。
#### 输出格式
  输出一行,包含一个整数,表示满足条件的方案数。由于这个数很大,请输出方案数除以100000007的余数。
#### 样例输入
```4 10 2 3```
#### 样例输出
```2```
#### 样例说明
这两个数列分别是```2 4 1 3```和```7 4 1 -2```
#### 数据规模和约定
对于10%的数据,1<=n<=5,0<=s<=5,1<=a,b<=5;
对于30%的数据,1<=n<=30,0<=s<=30,1<=a,b<=30;
对于50%的数据,1<=n<=50,0<=s<=50,1<=a,b<=50;
对于70%的数据,1<=n<=100,0<=s<=500,1<=a, b<=50;
对于100%的数据,1<=n<=1000,-1,000,000,000<=s<=1,000,000,000,1<=a, b<=1,000,000。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=1e3+5;
const int mod=100000007;
int n,s,a,b,up;
ll v;
int dp[2][N*(N+1)/2],now;
int ans;
int main()
{
scanf("%d%d%d%d",&n,&s,&a,&b);
dp[now][0]=1;
for(int i=1;i<n;++i)//只有n-1个增量
{
now=!now;
up=i*(i+1)/2;
for(int j=0;j<=up;++j)//01背包 容量 方案数
{
dp[now][j]=dp[!now][j];
if(j>=i)dp[now][j]=(dp[now][j]+dp[!now][j-i])%mod;
}
}
for(int i=0;i<=up;++i)//s-i*a-(n*(n-1)/2-i)*b 是否被n整除
{
v=1ll*s-1ll*i*a+1ll*(up-i)*b;
if(v%n==0)ans=(ans+dp[now][i])%mod;
}
printf("%d\n",ans);
return 0;
}
\ No newline at end of file
import java.util.Scanner;
public class Main {
static int n, s, a, b;
static int f[][];
static int modnum = 100000007;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
s = sc.nextInt();
a = sc.nextInt();
b = sc.nextInt();
f = new int[n][n];
f[0][0] = 1;
System.out.println(c());
}
private static int c() {
if (n == 1)
return 1;
for (int j = 1; j < n; j++)
for (int i = 0; i < n; i++)
f[i][j] = (f[g(i - j * a)][j - 1] + f[g(i + j * b)][j - 1]) % modnum;
return f[g(s)][n - 1];
}
private static int g(int v) {
return ((v % n) + n) % n;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册