计软实验班小学期笔记(实时更新中)
前言:不到啊
求n种不同面额的纸币 任选m张 求总方案数
高中组合数学隔板法 公式 C(n+m-1,n)
int C(int n,int m) {
int ans=1;
for(int i=1;i<=m;i++) {
ans=ans*(n-m+i)/i;
}
return ans;
}
*热知识:杨辉三角 n行m列对应的数字就是 C(n,m) (0行开始)
21位的花朵数
任务描述
编写一个程序来寻找所有21位的十进制正整数,这些整数的每个位上的数字的21次方之和等于该整数本身。
定义
- 花朵数:一个N位的十进制正整数,如果它的每个位上的数字的N次方之和等于这个数本身,则称其为花朵数。
- 例子:
- 当N=3时,153是一个花朵数,因为 1^3 + 5^3 + 3^3 = 153。
- 当N=4时,1634是一个花朵数,因为 1^4 + 6^4 + 3^4 + 4^4 = 1634。
- 当N=5时,92727是一个花朵数。
目标
求N=21时,所有满足条件的花朵数。输出所有符合条件的数字,每个数字占一行。
程序要求
- 输入:无
- 输出:所有21位的花朵数,每个数字占一行。
- 性能要求:程序应在1分钟内运行完毕。
示例输出
128468643043731391252
449177399146038697307
解题思路
由于直接枚举所有21位数所需时间非常大 根据花朵数的性质 我们可以dfs出0-9分别有几个
dfs所有可能隔板的位置
vector<vector<int>> ans;
void dfs(int n,int k,int st,vector<int>& path) {
if (path.size()==k) {
ans.push_back(path);
return;
}
for (int i=st;i<=n;i++) {
path.push_back(i);
dfs(n,k,i+1,path);
path.pop_back();
}
}
反转数组
分苹果
题目描述:现有m个苹果,以及n个盘子,将苹果放在盘子里(盘子可以不全有苹果),问:有几种方案?
样例:6 3
输出:7
买票上车
题目描述:现有m个有0.5元的人,n个有1元的人需要上公交车,已知公交车费0.5元,司机可以找零,但司机目前没有零钱。问:有几种上车方案可以让司机为乘客找零?
输入样例:3 2
输出样例:5
高IQ过河
话说有一家六口人,包括爸爸、妈妈、两个女儿及两个儿子在旅行途中迷了路,还不幸遇上了一个逃狱的犯人,幸好犯人让一个也在旅行的警察逮捕,一家六口才得以保住性命。可是,在荒郊野外,手机接受不灵,他们都不能与外界联络,连警察也不能找到支援,他们只有通过一条河流方能回家,能帮帮他们么?
玩家的任务是,帮助这些人渡过河,交通工具只有一艘小船。只有爸爸、妈妈以及警察能控制小船,此外,不论成人或是小孩,小船每次最多只能搭乘二人。在渡河期间,玩家还要防止以下三种情况发生:
1、当警察与犯人分开时,犯人会伤害一家六口。
2、当爸爸看见妈妈离开女儿时,爸爸便会教训女儿。
3、当妈妈看见爸爸离开儿子时,妈妈便会教训儿子。
#include <bits/stdc++.h>
using namespace std;
#define M 100005
#define N 1005
#define MOD (1e9+7)
#define lowbit(x) (x & (-x))
int dx[8] = {0, 0, 1, -1, 1, -1, 1, -1};
int dy[8] = {1, -1, 0, 0, -1, 1, 1, -1};
enum {
JC = 128,
XT = 64,
BB = 32,
DR = 16,
ER = 8,
MM = 4,
DY = 2,
EY = 1
};
bool f1(int x, int y)
{
return (x & y) == y;
}
bool f2(int x)
{
if (x < 128 && x>64) return false;
if(f1(x,BB)&&!f1(x,MM)&&(f1(x,DY)||f1(x,EY)))return false;
if (!f1(x, BB) && f1(x, MM) && (f1(x, DR) || f1(x, ER)))return false;
return true;
}
int kn[15] = {
JC | XT,JC | BB,JC | DR,JC | ER,JC | MM,
JC | DY,JC | EY,JC,BB | DR,BB | ER,BB | MM,BB,
MM | DY,MM | EY,MM };
bool v[512];
using namespace std;
void f(int x, int a[], int step)
{
if (x == 0)
{
int i;
for (i = 0; i < step; i++)
cout << a[i] << " ";
cout << endl;
return;
}
for ( int i = 0; i < 15; i++)
{
if (step % 2 == 0)
{
if (!f1(x, kn[i])) continue;
if (!f2(x- kn[i])) continue;
if (!f2(255-x + kn[i])) continue;
if(v[x-kn[i]])continue;
v[x - kn[i]] = true;
a[step] = kn[i];
f(x - kn[i], a, step + 1);
} else {
if (!f1(255 - x, kn[i])) continue;
if (!f2(255 - x - kn[i])) continue;
if (!f2(x + kn[i])) continue;
if (v[256 + x + kn[i]])continue;
v[256 + x + kn[i]] = true;
a[step] = kn[i];
f(x + kn[i], a, step + 1);
}
}
}
int main()
{
int a[30];
f(255,a,0);
}
张老师的生日
题目描述
小明和小强都是张老师的学生,张老师的生日是M月N日,2人都知道张老师的生日是下列10组中的一天:
3月4日 3月5日 3月8日
6月4日 6月7日
9月1日 9月5日
12月1日 12月2日 12月8日
张老师将M值告诉了小明,将N值告诉了小强,张老师问他们知道他的生日是哪一天吗?
小明说:如果我不知道的话,小强肯定不知道
小强说:本来我也不知道,但是现在我知道了
小明说:哦,那我也知道了
据上面信息,推断出张老师的生日是哪一天?
猜数
有两个大于1小于100的自然数x,y,老师告诉小明两个数的和,告诉小强两个数的积。已知小明和小强足够聪明。
下面是两个人的对话:
小强:我不知道这两个数是多少,你肯定也不知道
小明:我本来不知道,但你这么我说,我就不知道了。
小强:那现在我知道了。
问这两个数是多少?
DFS与BFS
八皇后
最少砝码
题目描述
你有一架天平。现在你要设计一套砝码,使得利用这些砝码可以称出任意 小于等于 N 的正整数重量。
那么这套砝码最少需要包含多少个砝码?
注意砝码可以放在天平两边。
输入格式
输入包含一个正整数 N。
输出格式
输出一个整数代表答案。
样例输入
7
样例输出
3
样例说明
3 个砝码重量是 1、4、6 可以称出 1 至 7 的所有重量。
1 = 1;
2 = 6 – 4
3 = 4 − 1;
4 = 4;
5 = 6 − 1;
6 = 6;
7 = 1 + 6;
少于 3 个砝码不可能称出 1 至 7 的所有重量。
评测用例规模与约定
对于所有评测用例,1 \leqslant N \leqslant 1000000000
运行限制
最大运行时间:1s
最大运行内存: 512M
八数码拼图
题目描述
在 3\times 3 的棋盘上,摆有八个棋子,每个棋子上标有 1 至 8 的某一数字。棋盘中留有一个空格,空格用 0 来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为 123456780),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
类似题目:P1379 八数码难题 - 洛谷
我的解法
使用BFS找到出最短的路径并用map记录上一个状态
#include <bits/stdc++.h>
using namespace std;
#define M 100005
#define N 1005
#define MOD (1e9+7)
#define lowbit(x) (x & (-x))
int dx[8] = {0, 0, 1, -1, 1, -1, 1, -1};
int dy[8] = {1, -1, 0, 0, -1, 1, 1, -1};
#define int long long
vector<int> random() { //随机生成一组测试样例
vector<int> mp;
bool vis[11]={false};
while (mp.size()<9) {
std::random_device rd;
std::mt19937 generator(rd());
int r = generator();
r%=9;
if (vis[r]==0) {
mp.push_back(r);
vis[r]=true;
}
}
return mp;
}
void out1(string &v) {
// cout<<v<<"\n";
for (int i=0;i<v.size();i++) {
cout<<v[i]<<" ";
if ((i+1) %3==0) {
cout<<"\n";
}
}
cout<<"\n";
}
void out2(vector<int> &v) {
for (int i=0;i<v.size();i++) {
cout<<v[i]<<" ";
if ((i+1) %3==0) {
cout<<"\n";
}
}
}
bool check(vector<int> &v) { //检查
int sum=0;
for (int i=0;i<v.size();i++) {
for (int j=i+1;j<v.size();j++) {
if (v[i]>v[j]) {
sum++;
}
}
}
if (sum%2==1) return true;
return false;
}
bool ok(vector<int>&v) {
if (v.size()!=9) return false;
for (int i=0;i<v.size()-1;i++) {
if (v[i]!=i+1) return false;
}
if (v[v.size()-1]!=0) return false;
return true;
}
unordered_map<string,string> str;
int bfs(string st) {
string ed="123456780";//目标状态
queue<string> q;
unordered_map<string,int> mp;
q.push(st);
mp[st]=0;
str.clear();
while (!q.empty()) {
auto t=q.front();
auto be=t;
q.pop();
// cout<<t<<"\n";
int d=mp[t];
if (t==ed) {
return d;
}
int z=t.find('0');
int x=z/3,y=z%3;
for (int i=0;i<4;i++) {
int a=x+dx[i];
int b=y+dy[i];
if (a>=0&&a<3&&b>=0&&b<3) {
// string next=t;
swap(t[z],t[a*3+b]);
if (!mp.count(t)) {
mp[t]=d+1;
q.push(t);
str[t]=be;
}
swap(t[z],t[a*3+b]);
}
}
}
return -1;
}
string tostring(vector<int> v) {
string s;
for (int i=0;i<v.size();i++) {
s+=to_string(v[i]);
}
return s;
}
void solve() {
vector<int> v=random();
out2(v);
cout<<endl;
string s="123456780";
int d = bfs(tostring(v));
if (d==-1) {
cout << "NO" << endl;
return;
}else {
cout << "YES" << endl;
// return;
}
stack<string> st;
while (s!=tostring(v)) {//从原状态到目标状态 搜索路径并入栈
st.push(s);
s=str[s];
}
int n=st.size();
while (!st.empty()) { //输出路径
cout<<n-st.size()+1<<endl;
out1(st.top());
cout<< endl;
st.pop();
}
cout << d << endl;
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr), std::cout.tie(nullptr);
int t = 1;
// std::cin >> t;
while (t--) {
solve();
}
return 0;
}
随机用例
7 4 6
0 8 5
1 2 3
YES
1
7 4 6
1 8 5
0 2 3
2
7 4 6
1 8 5
2 0 3
3
7 4 6
1 8 5
2 3 0
4
7 4 6
1 8 0
2 3 5
5
7 4 6
1 0 8
2 3 5
6
7 4 6
0 1 8
2 3 5
7
0 4 6
7 1 8
2 3 5
8
4 0 6
7 1 8
2 3 5
9
4 1 6
7 0 8
2 3 5
10
4 1 6
7 3 8
2 0 5
11
4 1 6
7 3 8
0 2 5
12
4 1 6
0 3 8
7 2 5
13
0 1 6
4 3 8
7 2 5
14
1 0 6
4 3 8
7 2 5
15
1 3 6
4 0 8
7 2 5
16
1 3 6
4 2 8
7 0 5
17
1 3 6
4 2 8
7 5 0
18
1 3 6
4 2 0
7 5 8
19
1 3 0
4 2 6
7 5 8
20
1 0 3
4 2 6
7 5 8
21
1 2 3
4 0 6
7 5 8
22
1 2 3
4 5 6
7 0 8
23
1 2 3
4 5 6
7 8 0
23