L1-102 兰州牛肉面、 L1-103 整数的持续性、L1-104 九宫格
L1-102 兰州牛肉面
题目
兰州牛肉面是历史悠久的美食,根据牛肉面的宽窄、配料的种类,可以细分为上百个不同的品种。你进到兰州的任何一家牛肉面馆,只说:“来一碗牛肉面!”就好像进到加州的咖啡馆说“来一杯咖啡”一样,会被店主人当成外星人……
本题的任务是,请你写程序帮助一家牛肉面馆的老板统计一下,他们一天卖出各种品种的牛肉面有多少碗,营业额一共有多少。
输入格式
输入第一行给出一个正整数 N(≤100),为牛肉面的种类数量。这里为了简单起见,我们把不同种类的牛肉面从 1 到 N 编号,以后就用编号代替牛肉面品种的名称。第二行给出 N 个价格,第 i 个价格对应第 i 种牛肉面一碗的单价。这里的价格是 [0.01, 200.00] 区间内的实数,以元为单位,精确到分。
随后是一天内客人买面的记录,每条记录占一行,格式为:
品种编号 碗数
其中碗数保证是正整数。当对应的 品种编号 为 0 时,表示输入结束。这个记录不算在内。
输出格式
首先输出 N 行,第 i 行输出第 i 种牛肉面卖出了多少碗。最后一行输出当天的总营业额,仍然是以元为单位,精确到分。题目保证总营业额不超过 10^6。
输入样例
5
4.00 8.50 3.20 12.00 14.10
3 5
5 2
1 1
2 3
2 2
1 9
0 0
输出样例
10
5
5
0
2
126.70
完整代码
#include <iostream>
#include <cstdio>
using namespace std;
int main() {
int n;
cin >> n; // 面的种类数
double price[105]; // 存每种面的价格
int cnt[105] = {0}; // 存每种面卖了多少碗,初始化为0
// 读入价格
for (int i = 1; i <= n; i++) {
cin >> price[i];
}
// 读入订单,直到 0 0 停止
int id, num;
while (cin >> id >> num) {
if (id == 0 && num == 0) break;
cnt[id] += num; // 对应品种累加碗数
}
// 输出每种面的销量
for (int i = 1; i <= n; i++) {
cout << cnt[i] << endl;
}
// 计算总营业额
double total = 0;
for (int i = 1; i <= n; i++) {
total += cnt[i] * price[i];
}
// 输出总金额,保留两位小数
printf("%.2f", total);
return 0;
}
#include<iostream>
#include <cstdio> // 必须添加,用于 printf
using namespace std;
int main(){
int n;//牛肉面的种类数量
double arr[105][2]={0};//arr[105][1]数量,arr[105][2]价格
cin>>n;
for(int i=0;i<n;i++){
cin>>arr[i][1];
}
int index,num;
while(cin>>index>>num){
if(index==0 && num==0) break;
arr[index-1][0]+=num;
}
double sum=0;
for(int i=0;i<n;i++){
cout << arr[i][0]<<endl;
sum+=arr[i][0]*arr[i][1];
};
printf("%.2f\n",sum);
return 0;
}
L1-103 整数的持续性
题目
从任一给定的正整数 n 出发,将其每一位数字相乘,记得到的乘积为 n1。以此类推,令 ni+1 为 ni 的各位数字的乘积,直到最后得到一个个位数 nm,则 m 就称为 n 的持续性。例如 679 的持续性就是 5,因为我们从 679 开始,得到 6×7×9=378,随后得到 3×7×8=168、1×6×8=48、4×8=32,最后得到 3×2=6,一共用了 5 步。
本题就请你编写程序,找出任一给定区间内持续性最长的整数。
输入格式
输入在一行中给出两个正整数 a 和 b(1≤a≤b≤10^9 且 (b−a)<10^3),为给定区间的两个端点。
输出格式
首先在第一行输出区间 [a,b] 内整数最长的持续性。随后在第二行中输出持续性最长的整数。如果这样的整数不唯一,则按照递增序输出,数字间以 1 个空格分隔,行首尾不得有多余空格。
输入样例
500 700
输出样例
5
679 688 697
代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 计算一个数字的持续性
int getLen(long long x) {
int cnt = 0;
while (x >= 10) {
long long p = 1;
// 计算各位乘积
while (x > 0) {
p *= x % 10;
x /= 10;
//小数直接扔掉,只留整数部分!
}
x = p;
cnt++;
}
return cnt;
}
int main() {
int a, b;
cin >> a >> b;
int max_len = -1;
vector<int> res;
for (int i = a; i <= b; i++) {
int now = getLen(i);
if (now > max_len) {
max_len = now;
res.clear();
res.push_back(i);
} else if (now == max_len) {
res.push_back(i);
}
}
// 输出
cout << max_len << endl;
for (int i = 0; i < res.size(); i++) {
if (i > 0) cout << " ";
cout << res[i];
}
cout << endl;
return 0;
}
1. 函数 getLen(x)
作用:计算数字 x 的持续性
- 循环:直到 x 变成 1 位数 停止
- 每一轮:把 x 的每一位相乘得到新数
- 每乘一轮,计数 +1
- 最终返回轮次(即持续性)
2. 主程序逻辑
- 遍历
[a, b]所有数字 - 记录最大持续性
max_len - 用
vector保存所有持续性最长的数字 - 按要求输出(自动递增,因为我们从小到大遍历)
3. 为什么用 long long
因为数字乘积可能爆 int,用 long long 保证不溢出。
999999999(9位)
各位相乘 = 9×9×9×9×9×9×9×9×9 = 387,420,489
这个数 超过 int 安全计算范围,用 int 会溢出出错!
所以:只要涉及“各位相乘” → 统一用 long long 最安全!
乘法、大数、位数相乘
int(整数,常用)
- 占 4字节
- 范围:-2147483648 ~ 2147483647
- 大约:-21亿 ~ 21亿
long(长整型)
- 和 int 一样大(多数编译器)
- 范围:-2147483648 ~ 2147483647
long long(长长整型)
- 占 8字节
- 范围:-9223372036854775808 ~ 9223372036854775807
- 大约:-900京 ~ 900京
- 做题遇到乘积、大数 → 必须用 long long
L1-104 九宫格
题目
L1-104 九宫格
分数 20
作者 陈越
单位 浙江大学
九宫格是一款数字游戏,传说起源于河图洛书,现代数学中称之为三阶幻方。游戏规则是:将一个 9×9 的正方形区域划分为 9 个 3×3 的正方形宫位,要求 1 到 9 这九个数字中的每个数字在每一行、每一列、每个宫位中都只能出现一次。
本题并不要求你写程序解决这个问题,只是对每个填好数字的九宫格,判断其是否满足游戏规则的要求。
输入格式
输入首先在第一行给出一个正整数 n(≤10),随后给出 n 个填好数字的九宫格。每个九宫格分 9 行给出,每行给出 9 个数字,其间以空格分隔。
输出格式
对每个给定的九宫格,判断其中的数字是否满足游戏规则的要求。满足则在一行中输出 1,否则输出 0。
输入样例
3
5 1 9 2 8 3 4 6 7
7 2 8 9 6 4 3 5 1
3 4 6 5 7 1 9 2 8
8 9 2 1 4 5 7 3 6
4 7 3 6 2 8 1 9 5
6 5 1 7 3 9 2 8 4
9 3 4 8 1 6 5 7 2
1 6 7 3 5 2 8 4 9
2 8 5 4 9 7 6 1 3
8 2 5 4 9 7 1 3 6
7 9 6 5 1 3 8 2 4
3 4 1 6 8 2 7 9 5
6 8 4 2 7 1 3 5 9
9 1 2 8 3 5 6 4 7
5 3 7 9 6 4 2 1 8
2 7 9 1 5 8 4 6 3
4 5 8 3 2 6 9 7 1
1 6 3 7 4 9 5 8 3
81 2 5 4 9 7 1 3 6
7 9 6 5 1 3 8 2 4
3 4 1 6 8 2 7 9 5
6 8 4 2 7 1 3 5 9
9 1 2 8 3 5 6 4 7
5 3 7 9 6 4 2 1 8
2 7 9 1 5 8 4 6 3
4 5 8 3 2 6 9 7 1
1 6 3 7 4 9 5 8 2
输出样例
1
0
0
完整代码(4种解法)
方法1:数组标记(最常用)
#include <iostream>
#include <cstring>
using namespace std;
// 检查3x3宫 (bx, by):0~2
bool checkBox(int a[9][9], int bx, int by) {
int cnt[10] = {0};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
int x = bx * 3 + i;
int y = by * 3 + j;
int num = a[x][y];
if (num < 1 || num > 9) return false; // 非法数字
cnt[num]++;
if (cnt[num] > 1) return false;
}
}
return true;
}
// 检查第row行
bool checkRow(int a[9][9], int row) {
int cnt[10] = {0};
for (int j = 0; j < 9; j++) {
int num = a[row][j];
if (num < 1 || num > 9) return false;
cnt[num]++;
if (cnt[num] > 1) return false;
}
return true;
}
// 检查第col列
bool checkCol(int a[9][9], int col) {
int cnt[10] = {0};
for (int i = 0; i < 9; i++) {
int num = a[i][col];
if (num < 1 || num > 9) return false;
cnt[num]++;
if (cnt[num] > 1) return false;
}
return true;
}
// 整体判断
bool isValid(int a[9][9]) {
// 检查所有行
for (int i = 0; i < 9; i++)
if (!checkRow(a, i)) return false;
// 检查所有列
for (int j = 0; j < 9; j++)
if (!checkCol(a, j)) return false;
// 检查所有3x3宫
for (int bx = 0; bx < 3; bx++)
for (int by = 0; by < 3; by++)
if (!checkBox(a, bx, by)) return false;
return true;
}
int main() {
int n, a[9][9];
cin >> n;
while (n--) {
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++)
cin >> a[i][j];
cout << (isValid(a) ? 1 : 0) << endl;
}
return 0;
}
方法2:求和判断(简单但有漏洞,仅辅助)
#include <iostream>
using namespace std;
// 宫求和(有漏洞:1+1+...+37=45)
bool checkBoxSum(int a[9][9], int bx, int by) {
int sum = 0;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
sum += a[bx*3+i][by*3+j];
return sum == 45;
}
bool checkRowSum(int a[9][9], int row) {
int sum = 0;
for (int j = 0; j < 9; j++) sum += a[row][j];
return sum == 45;
}
bool checkColSum(int a[9][9], int col) {
int sum = 0;
for (int i = 0; i < 9; i++) sum += a[i][col];
return sum == 45;
}
bool isValidSum(int a[9][9]) {
for (int i=0; i<9; i++) if (!checkRowSum(a,i)) return false;
for (int j=0; j<9; j++) if (!checkColSum(a,j)) return false;
for (int bx=0; bx<3; bx++)
for (int by=0; by<3; by++)
if (!checkBoxSum(a,bx,by)) return false;
return true;
}
int main() {
int n,a[9][9];
cin>>n;
while(n--) {
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
cin>>a[i][j];
// ⚠️ 仅求和会误判,必须搭配数字范围+重复检查
cout << (isValidSum(a) ? 1 : 0) << endl;
}
return 0;
}
方法3:set 去重
#include <iostream>
#include <set>
using namespace std;
bool checkBoxSet(int a[9][9], int bx, int by) {
set<int> s;
for (int i=0; i<3; i++) {
for (int j=0; j<3; j++) {
int num = a[bx*3+i][by*3+j];
if (num<1||num>9) return false;
s.insert(num);
}
}
return s.size() == 9;
}
bool checkRowSet(int a[9][9], int row) {
set<int> s;
for (int j=0; j<9; j++) {
int num = a[row][j];
if (num<1||num>9) return false;
s.insert(num);
}
return s.size() == 9;
}
bool checkColSet(int a[9][9], int col) {
set<int> s;
for (int i=0; i<9; i++) {
int num = a[i][col];
if (num<1||num>9) return false;
s.insert(num);
}
return s.size() == 9;
}
bool isValidSet(int a[9][9]) {
for (int i=0; i<9; i++) if (!checkRowSet(a,i)) return false;
for (int j=0; j<9; j++) if (!checkColSet(a,j)) return false;
for (int bx=0; bx<3; bx++)
for (int by=0; by<3; by++)
if (!checkBoxSet(a,bx,by)) return false;
return true;
}
int main() {
int n,a[9][9];
cin>>n;
while(n--) {
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
cin>>a[i][j];
cout << (isValidSet(a) ? 1 : 0) << endl;
}
return 0;
}
方法4:位运算
#include <iostream>
using namespace std;
bool checkBoxBit(int a[9][9], int bx, int by) {
int mask = 0;
for (int i=0; i<3; i++) {
for (int j=0; j<3; j++) {
int num = a[bx*3+i][by*3+j];
if (num<1||num>9) return false;
if (mask & (1 << num)) return false;
mask |= (1 << num);
}
}
return mask == 0b1111111110; // 二进制10位:第1~9位为1
}
bool checkRowBit(int a[9][9], int row) {
int mask = 0;
for (int j=0; j<9; j++) {
int num = a[row][j];
if (num<1||num>9) return false;
if (mask & (1 << num)) return false;
mask |= (1 << num);
}
return mask == 0b1111111110;
}
bool checkColBit(int a[9][9], int col) {
int mask = 0;
for (int i=0; i<9; i++) {
int num = a[i][col];
if (num<1||num>9) return false;
if (mask & (1 << num)) return false;
mask |= (1 << num);
}
return mask == 0b1111111110;
}
bool isValidBit(int a[9][9]) {
for (int i=0; i<9; i++) if (!checkRowBit(a,i)) return false;
for (int j=0; j<9; j++) if (!checkColBit(a,j)) return false;
for (int bx=0; bx<3; bx++)
for (int by=0; by<3; by++)
if (!checkBoxBit(a,bx,by)) return false;
return true;
}
int main() {
int n,a[9][9];
cin>>n;
while(n--) {
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
cin>>a[i][j];
cout << (isValidBit(a) ? 1 : 0) << endl;
}
return 0;
}
#include<iostream>
using namespace std;
int a[9][9];
// 检查所有 3×3 宫
bool check(int a[9][9]) {
int i = 0, j = 0;
// 遍历所有宫的起始行:0,3,6
while (i <= 6) {
j = 0;
// 遍历所有宫的起始列:0,3,6
while (j <= 6) {
int cnt[10] = {0}; // 每个宫重新计数
int k = 0, m = 0;
// 遍历宫内 3 行
while (k < 3) {
m = 0;
// 遍历宫内 3 列
while (m < 3) {
int num = a[i + k][j + m];
cnt[num]++;
// 重复了
if (cnt[num] > 1)
return false;
m++;
}
k++;
}
// 下一列宫
j += 3;
}
// 下一行宫
i += 3;
}
// 全部检查通过
return true;
}
//检查行
bool check_row(int a[9][9]){
int i, j ;
for(i = 0;i<9;i++){
int cnt[10] = {0};
for(j=0;j<9;j++){
cnt[a[i][j]-1]++;
// 重复了
if (cnt[a[i][j]-1] > 1){
return false;
}
}
}
// 全部检查通过
return true;
}
//检查列
bool check_col(int a[9][9]){
int i , j ;
for(i= 0;i<9;i++){
int cnt[10] = {0};
for(j= 0;j<9;j++){
cnt[a[j][i]-1]++;
// 重复了
if (cnt[a[j][i]-1] > 1){
return false;
}
}
}
// 全部检查通过
return true;
}
int main (){
int n;
cin>>n;
while(n--){
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
cin>>a[i][j];
}
}
if(check_col(a)&&check_row(a)&&check(a)){
cout <<"1";
if(n!=0){
cout<<endl;
}
}else{
cout <<"0";
if(n!=0){
cout<<endl;
}
}
}
return 0;
}
1078



被折叠的 条评论
为什么被折叠?



