工程伦理考试试题

1.单选题
有些工程产品(如DDT)在技术上是成功的,但在生态上是失败的。这句话的含义是:(D)
A 产品没有实现预期目的
B 产品亏损,经营难以为继
C 产品技术性能不如意
D 产品技术性能达到预期,但在生态效应方面却造成危害。

2.多选题
工程师容易忽视利益冲突的影响原因在于( BC)
A 认为只要遵循职业伦理章程的规范要求去行动,就不会造成利益冲突
B 可能会否认实际的存在利益冲突
C 可能高估自己处理利益冲突的能力
D 认为按照约定俗成的标准或以往的经验从事职业活动,就不会造成利益冲突

3.单选题
以下观点属于契约论的是( B)
A 关注的主要是人的内心品德的养成,而不是人外在行为的规则。
B 通过一个规则性的框架体系,把个人行为的动机和规范伦理地看作是一种社会协议。
C 关注人们行为的动机,强调行为的出发点要遵循道德的规范,体现人的义务和责任。
D 最好的结果就是达到“最大的善”,只有当一个行为能够最大化的

4.判断题
信息技术从业人员将所发明出来的信息技术开发成新产品、新服务后,往往会遭遇“制度真空”或“法律真空”地带,因此,加强信息技术从业人员的伦理意识培养、制定并执行职业规范非常重要。(对)

5.多选题
环境工程师一般建议遵守以下哪些准则(ABCD)
A 仅在他们有能力胜任的领域内从事工作。
B 仅以客观的和诚实的方式发表公开声明。
C 作为忠诚的代理人和受托人为雇主和客户从事职业工作。
D 将公众的安全、健康和福祉置于首位。

6.多选题
弱势人群包括(BCD)。
A 领导者
B 少数民族
C 妇女
D 儿童

7.判断题
在全球化情境下,只有充分重视工程的全球性特征,在尊重民族文化特色和地域文化前提下,工程实践才能有序运行。(对)

8.单选题
人与自然和谐发展是处理工程与自然关系的基本原则,其要求工程的决策者、设计者、实施者以及使用者都要了解和尊重自然的内在发展规律,不仅注重自然规律,更要注重(C)
A 经济规律
B 社会规律
C 生态规律
D 技术规律

9.多选题
影响核事故信息公开的主要因素包括(ABD)。
A 经济因素
B 社会因素
C 人文因素
D 政治因素

10.多选题
维护河流健康生命的原则包括:(ABCD)
A 补偿与损害等容
B 近期与远期统一
C 开发与保护并重
D 局部与整体协调

11.判断题
在讨论工程设计理念时,只需要工程师代表参与决策。(错)

12.多选题
跨文化工程伦理规范的国际运用涉及跨国企业的社会责任管理实践,其实质在于强调跨国企业不能只关注自己的经济利益,也应该致力于解决当地的社会问题。以下属于企业社会责任运动的实践成果的是:(ABCD)
A 社会责任国际组织的《社会责任国际标准》
B 联合国的《全球契约》
C 《中国对外承包工程行业社会责任指引》
D 国际标准化组织的《社会责任指南》

13.多选题
环境工程的主要任务有(ABCD)
A 治理污染
B 改善环境质量
C 提高生活水平
D 恢复生态

14.判断题
核安全基本原则主要涉及管理责任,纵深防御和基本技术原则。(对)

15.单选题
以下哪项是对马丁和辛津格的“利益冲突”定义的错误描述? (C)
A 工程师面对一种获得利益的可能性
B 这种转化是否能成功,取决于工程师的“行为”
C 是一种潜在利益冲突向实际利益冲突的转化的一种结果性情境
D 如果去追逐这种利益,那么可能就会使他们无法履行其对雇主或客户所应负有的义务

16.单选题
工程师在组织中的主要职能是(C)。
A 考虑所有相关的因素,维护组织利益
B 服从组织安排和上级命令,做好自己份内的工作
C 坚持职业标准,特别关注安全和质量标准
D 维护雇主和客户的利益

17.判断题
讨论工程的利益分配可以从宏观和微观两个层面来进行。宏观层面是指在企业内工程项目的活动情况。(错)

18.单选题
行业市场竞争不应该是(A)的竞争。
A 商业贿赂
B 技术
C 价格
D 服务

19.多选题
核工程师的培养,需重视培养他们的(AC)。
A 伦理道德
B 逻辑推理
C 社会责任感
D 学习能力

20.判断题
工程师的职业伦理标准中,要求当工程师发现任何形式的危害安全行为或不法行为时,要敢于采取应有的行动。(对)

21.单选题
工程实践全球化中工程师的伦理责任包括职业伦理责任、(D)、环境伦理责任、以及文化伦理责任
A 生态伦理责任
B 企业伦理责任
C 地球伦理责任
D 社会伦理责任

22.单选题
以下不属于安全文化的核心的是(D)。
A 人的安全意识
B 人的安全技能
C 人的安全知识
D 人的安全装备

23.单选题
涉及到人体的生物医学研究需要接受伦理审查,那么,伦理审查的最重要的目的是什么?(B)
A 保护研究者的权益
B 保障受试者权益
C 推进科研项目顺利开展
D 促进科学知识的增长

24.多选题
土木工程的伦理问题通常会涉及(ABC)等问题。
A 经济社会与环境可持续
B 利益分配公平与公正
C 安全与风险
D 公共治理。

25.判断题
环境问题主要指由于人类经济和社会活动引起的环境破坏,实质是经济发展与环境保护的冲突,是人与自然的失调。(对)

26.单选题
某跨国公司的工程师认为,分公司完全可以保持在自己国家行之有效的那套做法,不必根据新的跨文化环境进行调整。这种伦理立场属于:(C)
A 伦理拓展主义
B 伦理相对主义
C 伦理绝对主义
D 伦理关联主义

27.单选题
人的身份用来界定一个人是谁或者是什么,具有可识别性、独特性、唯一性。与人的身份不一样,数字身份具有多样性与(C),具有容易被盗用、容易被追溯等特点。
A 一致性
B 不变性
C 可变性
D 虚假性

28.多选题
狭义的工程概念认为,工程是以满足人类需求的目标为指向,应用各种相关的知识和技术手段,调动多种自然与社会资源,通过一群人的相互协作,将某些现有实体(自然的或人造的)汇聚并建造为具有预期使用价值的人造产品的过程。狭义的工程概念( ABCD)
A 强调多主体参与的社会性
B 包括“化学工程”“三峡工程”“载人航天工程”等
C 工程伦理所讨论的“工程”,主要指狭义的工程概念
D 主要指针对物质对象的、与生产实践密切联系、运用一定的知识和技术得以实现的人类活动

29.单选题
当某项工程在施工期间出现了技术规范所不允许的断层、裂缝、倾斜、倒塌、沉降、强度不足等情况时,监理工程师首先需要做的是?(A)
A 暂停该项工程的施工,并采取有效的安全措施。
B 要求承包人尽快提出质量事故报告并报告业主。
C 对承包人提出的有争议的质量事故责任予以判定。
D 对承包人提出的处理方案予以审查、修正、批准,并指令恢复该项工程施工。

30.判断题
目前对水利工程价值的伦理判断基本是遵循功利主义原则。(对)

31.单选题
2016年12月1日起实施的《中华人民共和国网络安全法》规定以下若干主体依法使用网络的权利受到国家保护。哪一个选项并未受到法律保护?(C)
A 其他组织
B 公民
C 实现自动驾驶的算法代码
D 法人

32.多选题
处理工程伦理问题的基本原则包括(BCD)
A 经济利益最大化原则
B 人与自然和谐发展原则
C 人道主义原则
D 社会公正原则

33.单选题
违背水资源公正配置原则的是(B)。
A 重视生态
B 自由引水
C 尊重历史
D 临近优先

34.判断题
涉及到人体的医学研究均应该接受伦理审查。(对)

35.单选题
下列哪一项不属于工程实践全球性特征?(A)
A 社会性
B 深远性
C 生态性
D 整体性

36.判断题
伦理责任就是法律责任(错)

37.多选题
以下哪些工程没有遵循自然规律,成为生态上失败的工程。(AB)
A 三门峡水利枢纽
B 咸海水利工程
C 三峡水利枢纽
D 里海水利工程

38.多选题
强化(法治、管理、技术)_手段,保证数据安全,是大数据应用的重要伦理法则。
(此题务必注意区分法治、法制)
A 法治
B 管理
C 法制
D 技术

39.判断题
工程师个人的职业理想、标准及其道德准则应无条件地服从就职公司的组织目标、政策、标准和行为,这样就不会遭遇利益冲突和角色冲突,更不会发生个人对组织的不服从行为。(错)

40.多选题
吸收公众参与工程决策、设计和实施的全过程,其作用是:(ABCD)

二叉树前序中序后序遍历非递归写法

三种遍历的大体流程是不一样的,主要的区别在于控制何时visit。

中序遍历:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
vector<int> inorderTraversal(TreeNode* root) {
if(!root) return {};
vector<int> ans;
stack<TreeNode*> s;
TreeNode *curr = root;
while(curr || !s.empty()) {
// Reach the left deep
while(curr) {
s.push(curr);
curr = curr->left;
}
// Backtrack from the empty subtree and visit the node at the top of the stack;
// however, if the stack is empty you are done
curr = s.top(); s.pop();
ans.push_back(curr->val); // visit
// We have visited the node and its left subtree. Now, its right subtree's turn
curr = curr->right;
}
return ans;
}

前序遍历:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
vector<int> preorderTraversal(TreeNode* root) {
if(!root) return {};
vector<int> ans;
stack<TreeNode*> s;
TreeNode *curr = root;
while(curr || !s.empty()) {
// Reach the left deep
while(curr) {
ans.push_back(curr->val); // visit
s.push(curr);
curr = curr->left;
}
// Backtrack from the empty subtree and visit the node at the top of the stack;
// however, if the stack is empty you are done
curr = s.top(); s.pop();
// We have visited the node and its left subtree. Now, its right subtree's turn
curr = curr->right;
}
return ans;
}

与中序的差别仅仅是访问的时机改到了Reach the left deep循环中,让左子树入栈前就可以先访问当前节点了。

后序遍历:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
vector<int> postorderTraversal(TreeNode* root) {
if(!root) return {};
vector<int> ans;
stack<TreeNode*> s;
TreeNode *curr = root;
TreeNode *lastvisited = nullptr;
while(curr || !s.empty()) {
// Reach the left deep
while(curr) {
s.push(curr);
curr = curr->left;
}
// Backtrack from the empty subtree and visit the node at the top of the stack;
// however, if the stack is empty you are done
curr = s.top(); // 不能在这弹出,要等到访问完右子树第二次经过父节点

if(!curr->right || lastvisited == curr->right) {
// 刚刚已经访问过右子树(根据lastvisited标记)或者没有右子树(所以没法产生lastvisited标记),现在访问当前节点(这是第二次经过)
ans.push_back(curr->val);
s.pop();
lastvisited = curr;
curr = nullptr; // 置为空,以便继续弹出父节点
} else {
// 右子树还没访问过,转向右子树
curr = curr->right;
}
}
return ans;
}

主要区别在于,由于是需要全部子树访问完再,所以对于同一个节点会经过两次,
第一次经过只是取出其右子树,
第二次从其右子树返回到当前节点才是应该访问的时机,

我们需要借助lastvisited判断当前是否是从其右子树返回的第二次经过,并在此时visit和pop。

不要忘记更新lastvisited,以当该结点是右孩子时协助其父节点更新,
不要忘记curr置空

调整博客架构,更换了主题与评论系统

很久没有打理博客了,将博客主题换成了Ayer,另外同样更换了评论系统为Valine,因为不需要额外加载站外js,相比Disqus更为流畅了。
旧评论的迁移上,写了个Disqus到Valine评论数据转换脚本转换。但由于Disqus不提供用户的邮箱地址和个人网站,这些数据无法迁移过来。

另外调整了博客架构,目前位于Github Page上使用GithubAction实现自动部署,免去了部署的烦恼,另外配合CDN实现了国内加速。

记录一下hexo升级

1
2
3
4
5
6
7
8
9
10
cnpm install -g npm-check           # 检查之前安装的插件,都有哪些是可以升级的 
cnpm install -g npm-upgrade # 升级系统中的插件
npm-check
npm-upgrade

# 更新 hexo 及所有插件
cnpm update

# 确认 hexo 已经更新
hexo -v

CCF201912-4 区块链

好像还是大模拟题。。
熟练运用STL,知晓其底层所用实现效率即可。。。
跟算法倒是没多大关系。。。

因为输入的查询必定晚于输入相关节点生成,实际上确保了查询时刻升序。
为了实现查询给定时刻的状态,记录所有输入与中间的节点传输数据,直到查询时再模拟运行到查询时刻,剩下的不模拟直到下一个查询时刻输入。

链的传输操作(transmission)和新块的创建操作(creation),使用哈希表unordered_map记录。
考虑到操作记录的信息量比较大,怕爆空间,完成操作处理后,会将其从哈希表中擦除。

为了按时间顺序处理,同时保证高效率+记录的时间点不能重复,使用set记录了所有发生变化操作的时间点(timepoints)。
在模拟时,从timepoints中顺序取出,即可按照时间点顺序处理,然后查询是否有对应时刻的transmission与creation。
在完成相应时刻的模拟之后,会移除set中对应的时间点。这是为了后续再次查询时不会重复处理已经处理过的时间点。

虽然transmission和creation擦除后,对应时间点的操作记录已经为空,那么timepoints即使不擦除已处理元素,也不会再影响结果正确性。但是如果不擦除timepoints,遍历时间点时仍然会造成时运行时间上的浪费。
timepoints已处理过的时间点必须动态擦除,否则重复遍历已处理过的时间点,会导致程序运行时间超时。
注意STL容器erase方法的用法

代码长度 3.234KB
编程语言 C0X
评测结果 正确
得分 100
时间使用 3.328s
空间使用 16.00MB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <bits/stdc++.h>
using namespace std;

using nodeidT = int;
using chainT = vector<nodeidT>;
using broadcastMsg = pair<nodeidT, chainT>; // 发出节点ID,主链
vector<vector<nodeidT> > rel; // 节点-邻接表{相连节点...}
vector<chainT> chain;// 节点-主链{主链节点...}
unordered_map<int, vector<pair<nodeidT, int>>> creation; // 时间- {{节点,块编号}...}
unordered_map<int, vector<broadcastMsg> > transmission; // 时间- {节点,链{接收链组成节点...}}...}
set<int> timepoints;

int n;
int delay;

inline void gen(int node, int t, int id) {
creation[t].push_back({node, id});
timepoints.insert(t);
}

inline void broadcastNeighbor(int node, int tp) {
transmission[tp + delay].push_back({node, chain[node]});
timepoints.insert(tp + delay); // 不要忘记维护时间点表
}

inline void query(int node, int t) {
auto it = timepoints.begin();
for (; it != timepoints.end() && *it <= t; ++it) {
int tp = *it;
// 先处理接收
if (transmission.count(tp)) {
for (const auto &msg: transmission[tp]) {
const auto &fromid = msg.first;
const auto &sentchain = msg.second;
for (const auto &toid: rel[fromid]) {
if (chain[toid].size() < sentchain.size()
|| (chain[toid].size() == sentchain.size() && chain[toid].back() > sentchain.back())
) {
chain[toid] = sentchain; // 接受更新
broadcastNeighbor(toid, tp); // 向邻居广播自己的主链
}
}
}
}
transmission.erase(tp);
// 处理创建
if (creation.count(tp)) {
for (const auto &p: creation[tp]) {
const auto &nodeid = p.first;
const auto &blockid = p.second;
chain[nodeid].push_back(blockid); // 主链延长
broadcastNeighbor(nodeid, tp); // 向邻居广播自己的主链
}
}
creation.erase(tp);
}
timepoints.erase(timepoints.begin(), it); // 此处erase使用注意,不能在循环中擦除当前key,否则当前迭代器失效无法自增至下一元素
// 输出该时间点状态
cout << chain[node].size();
for (int b: chain[node]) {
cout << " " << b;
}
cout << endl;
}

int main() {
ios_base::sync_with_stdio(false);
int m;
cin >> n >> m;
rel.resize(n + 1);
chain.resize(n + 1, chainT(1, 0));
creation.reserve(2000);
transmission.reserve(2000);
for (int i = 1; i <= m; ++i) {
int u, v;
cin >> u >> v;
rel[u].push_back(v);
rel[v].push_back(u);
}
int k;
cin >> delay >> k;
for (int i = 1; i <= k; ++i) {
int a, b, c;
cin >> a >> b;
if (cin.get() == '\n' || cin.eof()) {
query(a, b);
} else {
cin >> c;
gen(a, b, c);
}
}
}

CCF201912-3 化学方程式

用到编译原理的递归下降法,类似写语法分析器,
不过不需要生成AST,只需要统计元素个数即可。

代码长度 3.673KB
编程语言 C0X
评测结果 正确
得分 100
时间使用 156ms
空间使用 632.0KB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include <bits/stdc++.h>
using namespace std;
using element = string;

map<element, int> &operator+=(map<element, int> &a, const map<element, int> &b) {
for (const auto &p : b) {
a[p.first] += p.second;
}
return a;
}
map<element, int> operator*(int coef, const map<element, int> &b) {
map<element, int> r;
for (const auto &p : b) {
r[p.first] = p.second * coef;
}
return r;
}

map<element, int> parseTerm(const string &str);
map<element, int> parseFormula(const string &str);
size_t parseCOEF(const string &str, size_t pos, int &coef);

map<element, int> parseTerm(const string &str) {
map<element, int> r;
if (str.front() == '(') {
return parseFormula(str.substr(1, str.size() - 2));
}
++r[str];
return r;
}

map<element, int> parseFormula(const string &str) {
map<element, int> r;
size_t i = 0;
int level = 0;
string term;
while (i < str.size()) {
if (level > 0) {
if (str[i] == '(') {
++level;
} else if (str[i] == ')') {
--level;
}
term += str[i];
++i;
} else {

// 在level=0,只有小写才代表上一项没有结束。
if (islower(str[i])) {
term += str[i];
++i;
} else {
// level=0,非小写一律代表上一个符号已经结束。
// 此处处理
if (!term.empty()) {
int co = 0;
i += parseCOEF(str, i, co);
r += co * parseTerm(term);
term.clear();
}
if (str[i] == '(') {
++level;
term = str[i];
++i;
} else if (isupper(str[i])) {
term = str[i];
++i;
}
}

}

}
// 不要忘了最后可能还有一项,循环中可能没有处理。
if (!term.empty()) {
int co = 0;
parseCOEF(str, i, co);
r += co * parseTerm(term);
term.clear();
}
return r;
}

// 返回coef长度
size_t parseCOEF(const string &str, size_t pos, int &coef) {
if (pos >= str.size()) {
coef = 1;
return 0;
}
coef = 0;
size_t i = pos;
if (isdigit(str[i])) {
coef = str[i] - '0';
++i;
while (i < str.size() && isdigit(str[i])) {
coef = coef * 10 + (str[i] - '0');
++i;
}
} else {
coef = 1;
}
return i - pos;
}

map<element, int> parseExpr(const string &str) {
map<element, int> r;
size_t i = 0, ni = str.find('+');
if (ni == string::npos) {
int coef, coeflen;
coeflen = parseCOEF(str, 0, coef);
r += coef * parseFormula(str.substr(coeflen));
} else
while (i != string::npos) {
int coef, coeflen;
coeflen = parseCOEF(str, i, coef);
if (ni != string::npos) {
r += coef * parseFormula(str.substr(i + coeflen, ni - (i + coeflen)));
} else {
r += coef * parseFormula(str.substr(i + coeflen));
}
if (ni != string::npos) {
i = ni + 1;
ni = str.find('+', i);
} else {
i = ni;
}
}
return r;
}

bool legalEquation(const string &str) {
size_t i = str.find('=');
if (i == string::npos) return false;
return parseExpr(str.substr(0, i)) == parseExpr(str.substr(i + 1, str.size()));
}

int main() {
ios_base::sync_with_stdio(false);
int n;
cin >> n;
cin.get();
while (n--) {
string e;
getline(cin, e);
cout << (legalEquation(e) ? "Y" : "N") << endl;
}
}

CCF201912-1 报数

代码长度 1.161KB
编程语言 C0X
评测结果 正确
得分 100
时间使用 0ms
空间使用 672.0KB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <bits/stdc++.h>
using namespace std;
int times[4] = {0, 0, 0, 0};

bool skip(int x) {
if (x % 7 == 0) return true;
while (x > 0) {
if (x % 10 == 7) return true;
x /= 10;
}
return false;
}

int main() {
assert(!skip(6)); assert(!skip(1));
assert(skip(7)); assert(skip(17)); assert(skip(71)); assert(skip(711)); assert(skip(117)); assert(skip(171));
ios_base::sync_with_stdio(false);
// n: 要喊的数的数量
// i: 要喊的数
// cnt:已喊的数
int n, i=1;
cin >> n;
for(int cnt=0; cnt<n; i++) {
int who = (i-1)%4;
if(skip(i)) {
times[who]++;
} else {
cnt++;
}
}
cout << times[0] << endl
<< times[1] << endl
<< times[2] << endl
<< times[3] << endl;
}

CCF201912-2 回收站选址

代码长度 1.610KB
编程语言 C0X
评测结果 正确
得分 100
时间使用 15ms
空间使用 748.0KB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <bits/stdc++.h>
using namespace std;

set<pair<int, int>> p;
vector<int> cnt(5);
set<pair<int, int>> pre;

int main() {
ios_base::sync_with_stdio(false);
int n;
cin >> n;
int minx = 100000, miny = 100000;
int maxx = -1, maxy = -1;
while (n--) {
int xi, yi;
cin >> xi >> yi;
p.emplace(xi, yi);
pre.emplace(xi, yi);
pre.emplace(xi-1, yi);
pre.emplace(xi+1, yi);
pre.emplace(xi, yi-1);
pre.emplace(xi, yi+1);
if (xi < minx) {
minx = xi;
}
if (xi > maxx) {
maxx = xi;
}
if (yi < miny) {
miny = yi;
}
if (yi > maxy) {
maxy = yi;
}
}
for (auto xp : pre) {
int &xx = xp.first;
int &yy = xp.second;
if (p.count({xx, yy})
&& p.count({xx, yy - 1})
&& p.count({xx, yy + 1})
&& p.count({xx - 1, yy})
&& p.count({xx + 1, yy})
) {
int score = 0;
if (p.count({xx - 1, yy - 1})) {
++score;
}
if (p.count({xx - 1, yy + 1})) {
++score;
}
if (p.count({xx + 1, yy - 1})) {
++score;
}
if (p.count({xx + 1, yy + 1})) {
++score;
}
++cnt[score];
}
}
cout << cnt[0] << endl
<< cnt[1] << endl
<< cnt[2] << endl
<< cnt[3] << endl
<< cnt[4] << endl;
}

请我喝杯咖啡吧~

支付宝
微信