<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>GCD & LCM - 核心性质与公式</title>
<link rel="stylesheet" href="https://www.xinghuo.tv/wp-content/themes/xinghuo-tv/assets/katex/katex.min.css">
<script defer src="https://www.xinghuo.tv/wp-content/themes/xinghuo-tv/assets/katex/katex.min.js"></script>
<script defer src="https://www.xinghuo.tv/wp-content/themes/xinghuo-tv/assets/katex/auto-render.min.js"></script>
<script src="https://www.xinghuo.tv/wp-content/themes/xinghuo-tv/assets/js/vue.global.prod.js"></script>
<script src="https://www.xinghuo.tv/wp-content/themes/xinghuo-tv/assets/js/gsap.min.js"></script>
<style>
* {
box-sizing: border-box;
-webkit-tap-highlight-color: transparent;
}
html, body {
margin: 0;
padding: 0;
background: #F0F4F8;
overflow: hidden;
height: 100vh;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
-webkit-text-size-adjust: 100%;
}
#app {
height: 100vh;
width: 100%;
max-width: 480px;
margin: 0 auto;
background: #fff;
display: flex;
flex-direction: column;
box-shadow: 0 0 20px rgba(0,0,0,0.05);
}
.content-area {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
padding-bottom: 80px;
-webkit-overflow-scrolling: touch;
}
/* 顶部标签栏 */
.top-tabs {
display: flex;
background: linear-gradient(135deg, #8B5CF6 0%, #7C3AED 100%);
padding: 10px 10px 0 10px;
gap: 5px;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
.top-tab {
flex-shrink: 0;
padding: 10px 12px;
border-radius: 12px 12px 0 0;
font-size: 12px;
font-weight: bold;
color: rgba(255,255,255,0.7);
cursor: pointer;
transition: all 0.3s;
background: rgba(255,255,255,0.1);
min-width: 80px;
text-align: center;
}
.top-tab.active {
background: white;
color: #7C3AED;
transform: translateY(-2px);
box-shadow: 0 -2px 10px rgba(0,0,0,0.1);
}
/* 底部导航 */
.bottom-nav {
position: fixed;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 100%;
max-width: 480px;
height: 70px;
background: white;
border-top: 1px solid #e0e0e0;
display: flex;
justify-content: space-around;
align-items: center;
z-index: 1000;
box-shadow: 0 -2px 10px rgba(0,0,0,0.05);
}
.nav-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
padding: 8px;
transition: all 0.3s;
color: #64748B;
}
.nav-item.active { color: #8B5CF6; }
.nav-icon { font-size: 24px; margin-bottom: 4px; }
.nav-label { font-size: 12px; font-weight: 500; }
/* 通用样式 */
.page-container { padding: 20px; }
.section-title {
font-size: 20px;
font-weight: 800;
color: #1E293B;
margin: 20px 0 15px 0;
display: flex;
align-items: center;
gap: 8px;
}
.card {
background: white;
border-radius: 12px;
padding: 20px;
margin-bottom: 15px;
box-shadow: 0 4px 15px rgba(0,0,0,0.05);
border: 1px solid #E2E8F0;
}
.tag {
display: inline-block;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
font-weight: bold;
margin-bottom: 8px;
}
.tag-blue { background: #E0F2FE; color: #0284C7; }
.tag-green { background: #D1FAE5; color: #065F46; }
.tag-orange { background: #FFEDD5; color: #C2410C; }
.tag-purple { background: #F3E8FF; color: #7C3AED; }
.formula-box {
background: linear-gradient(135deg, #F3E8FF 0%, #E9D5FF 100%);
padding: 20px;
border-radius: 12px;
border: 3px solid #8B5CF6;
margin: 15px 0;
text-align: center;
}
.formula-title {
font-size: 14px;
font-weight: bold;
color: #7C3AED;
margin-bottom: 10px;
}
.formula-content {
font-size: 18px;
font-weight: bold;
color: #1E293B;
}
.speak-btn {
background: linear-gradient(135deg, #8B5CF6 0%, #7C3AED 100%);
color: white;
border: none;
padding: 12px 20px;
border-radius: 20px;
font-size: 14px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
box-shadow: 0 4px 10px rgba(139, 92, 246, 0.3);
width: 100%;
}
/* 动画舞台 */
.anim-stage {
background: #1E293B;
border-radius: 16px;
padding: 25px 15px;
min-height: 350px;
position: relative;
display: flex;
flex-direction: column;
align-items: center;
border: 2px solid #334155;
margin: 15px 0;
}
.anim-text {
color: white;
margin-top: auto;
font-size: 14px;
font-weight: bold;
text-align: center;
min-height: 60px;
background: rgba(0,0,0,0.4);
padding: 12px 15px;
border-radius: 20px;
backdrop-filter: blur(4px);
width: 100%;
display: flex;
align-items: center;
justify-content: center;
line-height: 1.5;
}
.step-controls {
display: flex;
gap: 10px;
margin-bottom: 15px;
justify-content: center;
flex-wrap: wrap;
}
.step-btn {
background: #8B5CF6;
color: white;
border: none;
padding: 8px 20px;
border-radius: 20px;
font-weight: bold;
font-size: 13px;
cursor: pointer;
transition: all 0.2s;
}
.step-btn:disabled { background: #CBD5E1; cursor: not-allowed; }
.step-btn:active:not(:disabled) { transform: scale(0.95); }
/* 计算演示 */
.calc-demo {
color: white;
width: 100%;
margin-top: 20px;
}
.calc-step {
background: rgba(255,255,255,0.1);
padding: 15px;
border-radius: 10px;
margin-bottom: 15px;
opacity: 0;
border: 2px solid transparent;
}
.calc-step.active {
border-color: #8B5CF6;
background: rgba(139, 92, 246, 0.2);
}
.calc-equation {
font-size: 16px;
text-align: center;
margin-bottom: 8px;
}
.calc-highlight {
color: #FCD34D;
font-size: 20px;
font-weight: bold;
}
.calc-explanation {
font-size: 12px;
color: #CBD5E1;
text-align: center;
margin-top: 5px;
}
/* 例题样式 */
.example-item {
border: 2px solid #E2E8F0;
border-radius: 10px;
margin-bottom: 12px;
overflow: hidden;
}
.example-header {
padding: 15px;
background: #F8FAFC;
font-weight: bold;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
font-size: 14px;
}
.example-content {
padding: 15px;
border-top: 1px solid #E2E8F0;
background: white;
line-height: 1.8;
font-size: 13px;
color: #334155;
display: none;
}
.example-item.active .example-content { display: block; }
.example-solution {
background: #F0FDF4;
padding: 15px;
border-radius: 8px;
margin-top: 10px;
border-left: 3px solid #10B981;
}
.step-by-step {
background: #EFF6FF;
padding: 12px;
border-radius: 8px;
margin: 10px 0;
border-left: 3px solid #3B82F6;
}
/* 练习题样式 */
.question-card {
background: white;
border-radius: 16px;
padding: 20px;
box-shadow: 0 4px 20px rgba(0,0,0,0.08);
margin-bottom: 15px;
}
.question-text {
font-size: 16px;
font-weight: bold;
margin-bottom: 15px;
line-height: 1.6;
color: #1E293B;
}
.answer-input {
width: 100%;
padding: 12px;
border: 2px solid #E2E8F0;
border-radius: 8px;
font-size: 16px;
margin-bottom: 10px;
}
.submit-btn {
background: #8B5CF6;
color: white;
border: none;
padding: 12px;
border-radius: 8px;
width: 100%;
font-weight: bold;
font-size: 16px;
cursor: pointer;
}
.feedback-box {
margin-top: 10px;
padding: 12px;
border-radius: 8px;
font-size: 13px;
line-height: 1.6;
}
.feedback-correct {
background: #ECFDF5;
color: #047857;
border: 2px solid #10B981;
}
.feedback-wrong {
background: #FEF2F2;
color: #B91C1C;
border: 2px solid #EF4444;
}
.property-card {
background: linear-gradient(135deg, #FEF3C7 0%, #FDE68A 100%);
padding: 15px;
border-radius: 12px;
margin: 15px 0;
border: 2px solid #F59E0B;
}
.property-title {
font-size: 15px;
font-weight: bold;
color: #92400E;
margin-bottom: 10px;
}
.property-formula {
background: white;
padding: 12px;
border-radius: 8px;
text-align: center;
font-size: 14px;
margin: 10px 0;
}
.visual-demo {
display: flex;
justify-content: space-around;
align-items: center;
padding: 20px;
flex-wrap: wrap;
gap: 15px;
}
.number-box {
width: 60px;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 10px;
font-size: 20px;
font-weight: bold;
color: white;
opacity: 0;
}
.operator {
font-size: 24px;
color: #FCD34D;
font-weight: bold;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
@keyframes glow {
0%, 100% { box-shadow: 0 0 10px rgba(139, 92, 246, 0.5); }
50% { box-shadow: 0 0 20px rgba(139, 92, 246, 0.8); }
}
</style><script>
document.addEventListener("DOMContentLoaded", function() {
renderMathInElement(document.body, {
delimiters: [
{left: "$$", right: "$$", display: true},
{left: "\\[", right: "\\]", display: true},
{left: "$", right: "$", display: false},
{left: "\\(", right: "\\)", display: false}
],
throwOnError: false
});
});
</script>
</head>
<body>
<div id="app">
<div class="content-area">
<!-- Page 1: 四大性质 -->
<div v-show="currentPage === 1">
<div class="top-tabs">
<div class="top-tab" :class="{active: propertyTab === 'product'}" @click="propertyTab = 'product'">
乘积关系
</div>
<div class="top-tab" :class="{active: propertyTab === 'coprime'}" @click="propertyTab = 'coprime'">
互质关系
</div>
<div class="top-tab" :class="{active: propertyTab === 'multiple'}" @click="propertyTab = 'multiple'">
倍数关系
</div>
<div class="top-tab" :class="{active: propertyTab === 'scale'}" @click="propertyTab = 'scale'">
同倍缩放
</div>
</div>
<div class="page-container">
<!-- 乘积关系 -->
<div v-show="propertyTab === 'product'">
<div class="section-title">🎯 性质1:乘积关系</div>
<div class="formula-box">
<div class="formula-title">★ 黄金公式 ★</div>
<div class="formula-content">
$A \times B = \text{GCD}(A, B) \times \text{LCM}(A, B)$
</div>
</div>
<div class="card">
<div class="tag tag-blue">公式含义</div>
<p style="font-size: 14px; color: #334155; line-height: 1.8; margin-top: 10px;">
两个数的<strong>乘积</strong> = 它们的<strong>最大公约数</strong> × <strong>最小公倍数</strong>
</p>
<div style="background: #FEF3C7; padding: 12px; border-radius: 8px; margin-top: 10px;">
<strong style="color: #92400E;">💡 记忆技巧:</strong><br>
知道三个,就能求第四个!
</div>
</div>
<div class="card">
<div class="tag tag-purple">动画演示</div>
<div class="step-controls">
<button class="step-btn" @click="animateProduct">▶️ 演示验证</button>
</div>
<div class="anim-stage">
<div class="visual-demo" id="product-demo">
<!-- 动画将在这里生成 -->
</div>
<div class="anim-text" id="product-text">点击按钮开始演示</div>
</div>
</div>
<div class="card">
<div class="tag tag-green">应用场景</div>
<div style="font-size: 13px; color: #334155; line-height: 1.8;">
<p><strong>📌 典型题型:</strong></p>
<div style="background: #EFF6FF; padding: 12px; border-radius: 6px; margin: 10px 0;">
• 已知两数乘积和GCD,求LCM<br>
• 已知两数乘积和LCM,求GCD<br>
• 已知一数、GCD和LCM,求另一数
</div>
</div>
</div>
<button class="speak-btn" @click="speakProduct">
🔊 听讲解
</button>
</div>
<!-- 互质关系 -->
<div v-show="propertyTab === 'coprime'">
<div class="section-title">🤝 性质2:互质关系</div>
<div class="formula-box">
<div class="formula-title">★ 互质公式 ★</div>
<div class="formula-content">
若 $\text{GCD}(A, B) = 1$,则 $\text{LCM}(A, B) = A \times B$
</div>
</div>
<div class="card">
<div class="tag tag-blue">什么是互质?</div>
<p style="font-size: 14px; color: #334155; line-height: 1.8; margin-top: 10px;">
两个数除了1以外,没有别的<strong>公约数</strong>,我们就说这两个数<strong>互质</strong>。
</p>
<div style="background: #F0FDF4; padding: 12px; border-radius: 8px; margin-top: 10px;">
<strong style="color: #065F46;">✅ 互质的例子:</strong><br>
• 3 和 5(相邻质数)<br>
• 8 和 9(相邻自然数)<br>
• 7 和 15(一个质数和一个合数)
</div>
</div>
<div class="card">
<div class="tag tag-purple">动画演示</div>
<div class="step-controls">
<button class="step-btn" @click="animateCoprime">▶️ 演示互质性质</button>
</div>
<div class="anim-stage">
<div class="visual-demo" id="coprime-demo">
<!-- 动画将在这里生成 -->
</div>
<div class="anim-text" id="coprime-text">点击按钮开始演示</div>
</div>
</div>
<div class="card">
<div class="tag tag-orange">特殊情况</div>
<div style="font-size: 13px; color: #334155; line-height: 1.8;">
<p><strong>🎯 一定互质的情况:</strong></p>
<div style="background: #FEF3C7; padding: 12px; border-radius: 6px; margin: 10px 0;">
1️⃣ <strong>相邻的两个自然数</strong>(如7和8)<br>
2️⃣ <strong>两个不同的质数</strong>(如3和7)<br>
3️⃣ <strong>1和任何数</strong>(1的特殊性)
</div>
</div>
</div>
<button class="speak-btn" @click="speakCoprime">
🔊 听讲解
</button>
</div>
<!-- 倍数关系 -->
<div v-show="propertyTab === 'multiple'">
<div class="section-title">📊 性质3:倍数关系</div>
<div class="formula-box">
<div class="formula-title">★ 倍数公式 ★</div>
<div class="formula-content">
若 $A$ 是 $B$ 的倍数,则<br>
$\text{GCD}(A, B) = B$(较小的)<br>
$\text{LCM}(A, B) = A$(较大的)
</div>
</div>
<div class="card">
<div class="tag tag-blue">公式含义</div>
<p style="font-size: 14px; color: #334155; line-height: 1.8; margin-top: 10px;">
如果 $A = B \times k$($A$是$B$的$k$倍),那么:
</p>
<div style="background: #EFF6FF; padding: 12px; border-radius: 8px; margin: 10px 0;">
• <strong>最大公约数</strong>就是小的那个数$B$<br>
• <strong>最小公倍数</strong>就是大的那个数$A$
</div>
</div>
<div class="card">
<div class="tag tag-purple">动画演示</div>
<div class="step-controls">
<button class="step-btn" @click="animateMultiple">▶️ 演示倍数关系</button>
</div>
<div class="anim-stage">
<div class="visual-demo" id="multiple-demo">
<!-- 动画将在这里生成 -->
</div>
<div class="anim-text" id="multiple-text">点击按钮开始演示</div>
</div>
</div>
<div class="card">
<div class="tag tag-green">理解要点</div>
<div style="font-size: 13px; color: #334155; line-height: 1.8;">
<p><strong>🎯 为什么是这样?</strong></p>
<div style="background: #F0FDF4; padding: 12px; border-radius: 6px; margin: 10px 0;">
因为大数$A$已经"包含"了小数$B$,所以:<br>
• 它们共同拥有的最大零件就是$B$<br>
• 能同时装下它们的最小仓库就是$A$
</div>
</div>
</div>
<button class="speak-btn" @click="speakMultiple">
🔊 听讲解
</button>
</div>
<!-- 同倍缩放 -->
<div v-show="propertyTab === 'scale'">
<div class="section-title">🔄 性质4:同倍缩放</div>
<div class="formula-box">
<div class="formula-title">★ 缩放公式 ★</div>
<div class="formula-content">
$\text{GCD}(kA, kB) = k \times \text{GCD}(A, B)$<br>
$\text{LCM}(kA, kB) = k \times \text{LCM}(A, B)$
</div>
</div>
<div class="card">
<div class="tag tag-blue">公式含义</div>
<p style="font-size: 14px; color: #334155; line-height: 1.8; margin-top: 10px;">
两个数同时<strong>乘以</strong>或<strong>除以</strong>同一个数$k$,它们的GCD和LCM也会同步变化$k$倍。
</p>
<div style="background: #FEF3C7; padding: 12px; border-radius: 8px; margin-top: 10px;">
<strong style="color: #92400E;">💡 神奇用途:</strong><br>
算大数时先缩小,算完再放大回去!
</div>
</div>
<div class="card">
<div class="tag tag-purple">动画演示</div>
<div class="step-controls">
<button class="step-btn" @click="animateScale">▶️ 演示缩放过程</button>
</div>
<div class="anim-stage">
<div class="calc-demo" id="scale-demo">
<!-- 动画将在这里生成 -->
</div>
<div class="anim-text" id="scale-text">点击按钮开始演示</div>
</div>
</div>
<div class="card">
<div class="tag tag-green">实战技巧</div>
<div style="font-size: 13px; color: #334155; line-height: 1.8;">
<p><strong>📌 例如求GCD(1200, 1600):</strong></p>
<div class="step-by-step">
<strong>步骤1:</strong>观察发现两数都是100的倍数<br>
<strong>步骤2:</strong>同时除以100 → 变成GCD(12, 16)<br>
<strong>步骤3:</strong>计算GCD(12, 16) = 4<br>
<strong>步骤4:</strong>乘回100 → GCD(1200, 1600) = 400
</div>
</div>
</div>
<button class="speak-btn" @click="speakScale">
🔊 听讲解
</button>
</div>
</div>
</div>
<!-- Page 2: 5道经典例题 -->
<div v-show="currentPage === 2">
<div class="top-tabs">
<div class="top-tab" :class="{active: exampleIndex === index}"
v-for="(ex, index) in classicExamples" :key="'tab-' + index"
@click="switchExample(index)">
例题{{ index + 1 }}
</div>
</div>
<div class="page-container">
<div v-for="(ex, index) in classicExamples" :key="'example-' + index"
v-show="exampleIndex === index">
<div class="section-title">{{ ex.title }}</div>
<div class="card">
<div class="tag tag-blue">题目</div>
<div class="question-text" v-html="ex.question"></div>
</div>
<div class="card">
<div class="tag tag-purple">分步解析</div>
<div class="step-controls">
<button class="step-btn" @click="prevExampleStep(index)" :disabled="exampleSteps[index] === 0">
◀ 上一步
</button>
<button class="step-btn" @click="nextExampleStep(index)" :disabled="exampleSteps[index] >= ex.steps.length - 1">
下一步 ▶
</button>
<button class="step-btn" @click="resetExampleStep(index)" style="background: #64748B;">
🔄 重置
</button>
</div>
<div class="anim-stage">
<div class="calc-demo">
<div v-for="(step, sIndex) in ex.steps" :key="'step-' + sIndex"
class="calc-step"
:class="{active: exampleSteps[index] === sIndex}"
:style="{opacity: exampleSteps[index] >= sIndex ? 1 : 0}">
<div class="calc-equation" v-html="step.equation"></div>
<div class="calc-explanation">{{ step.explanation }}</div>
</div>
</div>
<div class="anim-text">
{{ exampleSteps[index] < ex.steps.length ? ex.steps[exampleSteps[index]].text : ex.answer }}
</div>
</div>
</div>
<div class="card">
<div class="tag tag-green">答案</div>
<div class="example-solution" v-html="ex.answer"></div>
</div>
</div>
</div>
</div>
<!-- Page 3: 10道练习题 -->
<div v-show="currentPage === 3" class="page-container">
<div class="section-title">✏️ 10道练习题</div>
<div v-if="!practiceDone">
<div class="question-card">
<div class="tag tag-blue">练习 {{ currentPracticeIndex + 1 }}/10</div>
<div class="question-text" v-html="practiceQuestions[currentPracticeIndex].question"></div>
<input
type="text"
class="answer-input"
v-model="userAnswer"
placeholder="输入答案(可以是数字或分数,如7/11)"
@keyup.enter="checkPracticeAnswer"
:disabled="practiceAnswered">
<button class="submit-btn" @click="checkPracticeAnswer" v-if="!practiceAnswered">
提交答案
</button>
<div v-if="practiceAnswered" class="feedback-box" :class="isPracticeCorrect ? 'feedback-correct' : 'feedback-wrong'">
<div v-if="isPracticeCorrect" style="font-weight: bold; margin-bottom: 5px;">🎉 正确!</div>
<div v-else style="font-weight: bold; margin-bottom: 5px;">💡 答案:{{ practiceQuestions[currentPracticeIndex].answer }}</div>
<div v-html="practiceQuestions[currentPracticeIndex].explanation"></div>
</div>
<button v-if="practiceAnswered" class="submit-btn" @click="nextPractice" style="margin-top: 10px;">
{{ currentPracticeIndex < 9 ? '下一题 →' : '完成练习 🎯' }}
</button>
</div>
</div>
<div v-else class="card" style="text-align: center; padding: 40px 20px;">
<div style="font-size: 60px; margin-bottom: 20px;">🏆</div>
<h2 style="color: #1E293B; margin-bottom: 10px;">练习完成!</h2>
<p style="font-size: 18px; color: #64748B; margin-bottom: 30px;">得分:{{ practiceScore }}/100</p>
<button class="submit-btn" @click="switchPage(4)">挑战杯赛真题 →</button>
</div>
</div>
<!-- Page 4: 10道杯赛真题 -->
<div v-show="currentPage === 4" class="page-container">
<div class="section-title">🏆 10道杯赛真题</div>
<div class="card" style="background: linear-gradient(135deg, #FEF3C7 0%, #FDE68A 100%);">
<div style="font-size: 14px; color: #92400E; line-height: 1.6;">
<strong>💡 提示:</strong>这些题目来自华杯赛、希望杯、迎春杯等真题。<br>
需要灵活运用四大性质,难度较大!
</div>
</div>
<div v-if="!olympiadDone">
<div class="question-card">
<div class="tag tag-purple">🏆 杯赛真题 {{ currentOlympiadIndex + 1 }}/10</div>
<div class="question-text" v-html="olympiadQuestions[currentOlympiadIndex].question"></div>
<div v-if="olympiadQuestions[currentOlympiadIndex].hint"
style="background: #FEF3C7; padding: 12px; border-radius: 6px; margin-bottom: 10px; font-size: 13px;">
<strong>💡 提示:</strong>{{ olympiadQuestions[currentOlympiadIndex].hint }}
</div>
<input
type="text"
class="answer-input"
v-model="userOlympiadAnswer"
placeholder="输入答案"
@keyup.enter="checkOlympiadAnswer"
:disabled="olympiadAnswered">
<button class="submit-btn" @click="checkOlympiadAnswer" v-if="!olympiadAnswered">
提交答案
</button>
<div v-if="olympiadAnswered" class="feedback-box" :class="isOlympiadCorrect ? 'feedback-correct' : 'feedback-wrong'">
<div v-if="isOlympiadCorrect" style="font-weight: bold; margin-bottom: 5px;">🎉 正确!太棒了!</div>
<div v-else style="font-weight: bold; margin-bottom: 5px;">💡 正确答案:{{ olympiadQuestions[currentOlympiadIndex].answer }}</div>
<div style="margin-top: 10px;"><strong>详细解析:</strong></div>
<div v-html="olympiadQuestions[currentOlympiadIndex].explanation"></div>
</div>
<button v-if="olympiadAnswered" class="submit-btn" @click="nextOlympiad" style="margin-top: 10px;">
{{ currentOlympiadIndex < 9 ? '下一题 →' : '查看总结 📚' }}
</button>
</div>
</div>
<div v-else class="card" style="text-align: center; padding: 40px 20px;">
<div style="font-size: 60px; margin-bottom: 20px;">🥇</div>
<h2 style="color: #1E293B; margin-bottom: 10px;">杯赛真题通关!</h2>
<p style="font-size: 18px; color: #64748B; margin-bottom: 30px;">得分:{{ olympiadScore }}/100</p>
<p style="font-size: 14px; color: #64748B;">你已经掌握了GCD&LCM的核心性质!</p>
</div>
</div>
</div>
<!-- 底部导航 -->
<div class="bottom-nav">
<div class="nav-item" :class="{active: currentPage === 1}" @click="switchPage(1)">
<div class="nav-icon">🎯</div>
<div class="nav-label">性质</div>
</div>
<div class="nav-item" :class="{active: currentPage === 2}" @click="switchPage(2)">
<div class="nav-icon">📚</div>
<div class="nav-label">例题</div>
</div>
<div class="nav-item" :class="{active: currentPage === 3}" @click="switchPage(3)">
<div class="nav-icon">✏️</div>
<div class="nav-label">练习</div>
</div>
<div class="nav-item" :class="{active: currentPage === 4}" @click="switchPage(4)">
<div class="nav-icon">🏆</div>
<div class="nav-label">杯赛</div>
</div>
</div>
</div>
<script>
const { createApp } = Vue;
createApp({
data() {
return {
currentPage: 1,
propertyTab: 'product',
exampleIndex: 0,
// 例题步骤
exampleSteps: [0, 0, 0, 0, 0],
// 5道经典例题
classicExamples: [
{
title: '例题1:乘积公式的直接应用',
question: '已知两个自然数 $A$ 和 $B$,它们的乘积 $A \\times B = 432$,最大公约数 $\\text{GCD}(A, B) = 6$。<br>求这两个数的最小公倍数 $\\text{LCM}(A, B)$。',
steps: [
{
equation: '已知:$A \\times B = 432$',
explanation: '两数的乘积',
text: '第1步:明确已知条件'
},
{
equation: '已知:$\\text{GCD}(A, B) = 6$',
explanation: '两数的最大公约数',
text: '第2步:记录GCD的值'
},
{
equation: '使用公式:$A \\times B = \\text{GCD} \\times \\text{LCM}$',
explanation: '乘积关系公式',
text: '第3步:套用黄金公式'
},
{
equation: '$432 = 6 \\times \\text{LCM}$',
explanation: '代入数值',
text: '第4步:代入已知数值'
},
{
equation: '$\\text{LCM} = 432 \\div 6 =$ <span class="calc-highlight">72</span>',
explanation: '计算结果',
text: '第5步:计算得出答案'
}
],
answer: '<strong style="color: #8B5CF6; font-size: 18px;">答案:72</strong><br>通过乘积公式,只需简单的除法就能求出LCM!'
},
{
title: '例题2:互质关系的反向构造',
question: '两个自然数互质,它们的最小公倍数是 $35$。<br>求这两个数的和是多少?',
steps: [
{
equation: '已知:$\\text{GCD}(a, b) = 1$(互质)',
explanation: '两数互质',
text: '第1步:理解互质条件'
},
{
equation: '已知:$\\text{LCM}(a, b) = 35$',
explanation: '最小公倍数',
text: '第2步:记录LCM'
},
{
equation: '互质时:$\\text{LCM} = a \\times b$',
explanation: '互质性质',
text: '第3步:应用互质公式'
},
{
equation: '$a \\times b = 35$',
explanation: '转化为乘积问题',
text: '第4步:问题转化'
},
{
equation: '分解:$35 = 1 \\times 35 = 5 \\times 7$',
explanation: '找所有因数对',
text: '第5步:分解35'
},
{
equation: '检验互质:$(1, 35)$ 互质 ✓,$(5, 7)$ 互质 ✓',
explanation: '确认都满足互质条件',
text: '第6步:验证互质'
},
{
equation: '<span class="calc-highlight">和为:$1 + 35 = 36$</span> 或 <span class="calc-highlight">$5 + 7 = 12$</span>',
explanation: '计算两组和',
text: '第7步:计算各组和'
}
],
answer: '<strong style="color: #8B5CF6; font-size: 18px;">答案:36 或 12</strong><br>两种情况都符合题意:(1, 35) 或 (5, 7)'
},
{
title: '例题3:同倍缩放法算大数',
question: '求 $1200$ 和 $1600$ 的最大公约数和最小公倍数。',
steps: [
{
equation: '观察:$1200 = 12 \\times 100$,$1600 = 16 \\times 100$',
explanation: '提取公因数100',
text: '第1步:观察发现公因数'
},
{
equation: '缩小:除以100 → 求 $\\text{GCD}(12, 16)$',
explanation: '先算小数',
text: '第2步:同时缩小100倍'
},
{
equation: '$\\text{GCD}(12, 16) = 4$',
explanation: '计算小数的GCD',
text: '第3步:计算GCD(12,16)'
},
{
equation: '$\\text{LCM}(12, 16) = 48$',
explanation: '计算小数的LCM',
text: '第4步:计算LCM(12,16)'
},
{
equation: '还原:<span class="calc-highlight">$\\text{GCD}(1200, 1600) = 4 \\times 100 = 400$</span>',
explanation: '乘回100',
text: '第5步:GCD还原放大'
},
{
equation: '还原:<span class="calc-highlight">$\\text{LCM}(1200, 1600) = 48 \\times 100 = 4800$</span>',
explanation: '乘回100',
text: '第6步:LCM还原放大'
}
],
answer: '<strong style="color: #8B5CF6; font-size: 18px;">答案:GCD=400,LCM=4800</strong><br>同倍缩放让大数计算变简单!'
},
{
title: '例题4:比例与公约数',
question: '两个数的比是 $3:4$,它们的最大公约数是 $5$。<br>求这两个数的最小公倍数。',
steps: [
{
equation: '比例:$a : b = 3 : 4$',
explanation: '两数的比',
text: '第1步:理解比例关系'
},
{
equation: '设:$a = 3k$,$b = 4k$',
explanation: 'k是公因数',
text: '第2步:用k表示两数'
},
{
equation: '已知:$\\text{GCD}(3k, 4k) = 5$',
explanation: '最大公约数条件',
text: '第3步:应用GCD条件'
},
{
equation: '由同倍性质:$\\text{GCD}(3k, 4k) = k \\times \\text{GCD}(3, 4)$',
explanation: '使用同倍缩放',
text: '第4步:套用同倍公式'
},
{
equation: '$k \\times 1 = 5$(因为3和4互质)',
explanation: 'GCD(3,4)=1',
text: '第5步:计算k值'
},
{
equation: '$k = 5$,所以 $a = 15$,$b = 20$',
explanation: '求出具体数值',
text: '第6步:确定两个数'
},
{
equation: '<span class="calc-highlight">$\\text{LCM}(15, 20) = 60$</span>',
explanation: '计算最小公倍数',
text: '第7步:计算LCM'
}
],
answer: '<strong style="color: #8B5CF6; font-size: 18px;">答案:60</strong><br>也可以用公式:$\\text{LCM} = 5 \\times \\text{LCM}(3, 4) = 5 \\times 12 = 60$'
},
{
title: '例题5:倍数关系的陷阱',
question: '$A$ 是 $B$ 的因数(且 $A \\neq B$),已知 $\\text{LCM}(A, B) = 30$。<br>求 $B$ 是多少?',
steps: [
{
equation: '已知:$A$ 是 $B$ 的因数',
explanation: '即B是A的倍数',
text: '第1步:理解倍数关系'
},
{
equation: '倍数关系性质:$\\text{LCM}(A, B) = B$(较大数)',
explanation: '关键公式',
text: '第2步:应用倍数性质'
},
{
equation: '已知:$\\text{LCM}(A, B) = 30$',
explanation: 'LCM的值',
text: '第3步:代入已知条件'
},
{
equation: '<span class="calc-highlight">直接得出:$B = 30$</span>',
explanation: '答案一步到位',
text: '第4步:得出答案'
}
],
answer: '<strong style="color: #8B5CF6; font-size: 18px;">答案:30</strong><br>倍数关系下,LCM就是较大的那个数!'
}
],
// 练习题
currentPracticeIndex: 0,
practiceScore: 0,
practiceAnswered: false,
isPracticeCorrect: false,
userAnswer: '',
practiceDone: false,
practiceQuestions: [
{question: '已知 $a \\times b = 100$,$\\text{GCD}(a, b) = 5$,求 $\\text{LCM}(a, b)$', answer: '20', explanation: '使用公式:$\\text{LCM} = (a \\times b) \\div \\text{GCD} = 100 \\div 5 = 20$'},
{question: '已知 $\\text{GCD}(a, b) = 1$(互质),且 $a \\times b = 20$,求 $\\text{LCM}(a, b)$', answer: '20', explanation: '互质时 $\\text{LCM} = a \\times b = 20$'},
{question: '求 $\\text{LCM}(300, 500)$(提示:先缩放)', answer: '1500', explanation: '提取100:$100 \\times \\text{LCM}(3, 5) = 100 \\times 15 = 1500$'},
{question: '已知 $A$ 是 $B$ 的倍数,且 $A=24$,求 $\\text{LCM}(A, B)$', answer: '24', explanation: '倍数关系,$\\text{LCM}$ 是较大的数 $A = 24$'},
{question: '已知 $\\text{GCD}(a, b) = 10$,$\\text{LCM}(a, b) = 100$,求 $a \\times b$', answer: '1000', explanation: '乘积 $= \\text{GCD} \\times \\text{LCM} = 10 \\times 100 = 1000$'},
{question: '判断:两个数的最小公倍数一定是它们最大公约数的倍数(输入"对"或"错")', answer: '对', explanation: '正确!$\\text{LCM}$ 包含所有质因数,$\\text{GCD}$ 是公共质因数,必然包含'},
{question: '若 $a = 3b$,则 $\\text{GCD}(a, b)$ 等于多少?(用b表示)', answer: 'b', explanation: '因为 $a$ 是 $b$ 的倍数,$\\text{GCD}$ 是较小数 $b$'},
{question: '已知两个质数 $P$ 和 $Q$,求 $\\text{LCM}(P, Q)$(用P和Q表示,如P*Q)', answer: 'P*Q', explanation: '质数互质,$\\text{LCM} = P \\times Q$'},
{question: '求 $\\text{GCD}(150, 250)$(提示:同倍缩放)', answer: '50', explanation: '$50 \\times \\text{GCD}(3, 5) = 50 \\times 1 = 50$'},
{question: '已知两数乘积是60,最小公倍数是30,求最大公约数', answer: '2', explanation: '$\\text{GCD} = (a \\times b) \\div \\text{LCM} = 60 \\div 30 = 2$'}
],
// 杯赛真题
currentOlympiadIndex: 0,
olympiadScore: 0,
olympiadAnswered: false,
isOlympiadCorrect: false,
userOlympiadAnswer: '',
olympiadDone: false,
olympiadQuestions: [
{
question: '(希望杯 真题)已知两个自然数 $A$ 和 $B$ 的乘积是 $192$,它们的最大公约数是 $4$。求它们的最小公倍数。',
answer: '48',
hint: '使用乘积公式',
explanation: '<strong>解析:</strong><strong>$\\text{LCM} = (A \\times B) \\div \\text{GCD} = 192 \\div 4 = 48$</strong>'
},
{
question: '(华杯赛 真题)两个自然数的最大公约数是 $6$,最小公倍数是 $72$。已知其中一个数是 $18$,另一个数是多少?',
answer: '24',
hint: '使用公式 A×B = GCD×LCM',
explanation: '<strong>解析:</strong><strong>$18 \\times B = 6 \\times 72$ → $B = 432 \\div 18 = 24$</strong>'
},
{
question: '(迎春杯 真题)已知 $a$ 和 $b$ 互质,且 $\\text{LCM}(a, b) = 63$。求 $a$ 和 $b$ 的值可能有几组?(不考虑顺序)',
answer: '2',
hint: '互质时LCM = a×b,分解63',
explanation: '<strong>解析:</strong>$a \\times b = 63 = 3^2 \\times 7$<br>互质组合:$(1, 63)$ 和 $(7, 9)$<br>共<strong>2组</strong>'
},
{
question: '(走美杯 真题)两个数的最大公约数是 $15$,最小公倍数是 $180$。这两个数相差 $15$,求这两个数。',
answer: '45,60',
hint: '设两数为15x和15y,其中x,y互质',
explanation: '<strong>解析:</strong>设 $a=15x, b=15y$($x,y$ 互质)<br>$15xy = 180$ → $xy = 12$<br>$15(x-y) = 15$ → $x-y = 1$<br>积12差1的互质数:$(3, 4)$<br>数是 <strong>15 \\times 3 = 45$ </strong>和 $15 \\times 4 = <strong>60</strong>$'
},
{
question: '(中环杯 真题)已知 $a, b$ 都是两位数,且 $\\text{GCD}(a, b) = 6$,$\\text{LCM}(a, b) = 90$。求 $a + b$ 的值。',
answer: '48',
hint: '用乘积公式求a×b,再分解',
explanation: '<strong>解析:</strong>$a \\times b = 6 \\times 90 = 540$<br>设 $a=6x, b=6y$($x,y$ 互质)<br>$36xy = 540$ → $xy = 15$<br>互质对:$(3, 5)$<br>数是 $18$ 和 $30$<br>和 $= 18 + 30 = <strong>48</strong>$'
},
{
question: '(高难度)已知 $\\text{GCD}(x, y) = 5$,$\\text{LCM}(x, y) = 120$。求 $x$ 和 $y$ 的和最小是多少?',
answer: '55',
hint: '求xy,再分解成互质对',
explanation: '<strong>解析:</strong>$xy = 5 \\times 120 = 600$<br>设 $x=5m, y=5n$($m,n$ 互质)<br>$25mn = 600$ → $mn = 24$<br>互质对:$(1,24)$和为125,$(3,8)$和为55<br>最小和 $= <strong>55</strong>$'
},
{
question: '(思维题)$A$ 和 $B$ 的最大公约数是 $12$,$A$ 和 $B$ 的和是 $60$。求 $\\text{LCM}(A, B)$。',
answer: '48或72',
hint: '设A=12m, B=12n',
explanation: '<strong>解析:</strong>设 $A=12m, B=12n$<br>$12(m+n) = 60$ → $m+n = 5$<br>互质对:$(1,4)$或$(2,3)$<br>$(1,4)$:$A=12, B=48$,$\\text{LCM}=48$<br>$(2,3)$:$A=24, B=36$,$\\text{LCM}=72$'
},
{
question: '(奥数经典)两数乘积 $3150$,最大公约数 $15$。这两数之差最小是多少?',
answer: '75',
hint: '设两数为15x和15y',
explanation: '<strong>解析:</strong>设 $a=15x, b=15y$<br>$225xy = 3150$ → $xy = 14$<br>互质对:$(1,14)$差195,$(2,7)$差75<br>最小差 $= 15 \\times 5 = <strong>75</strong>$'
},
{
question: '(挑战题)已知 $a, b, c$ 互不相等,$\\text{GCD}(a,b)=\\text{GCD}(b,c)=\\text{GCD}(a,c)=15$。若 $a \\times b \\times c = 33750$,求 $\\text{LCM}(a,b,c)$。',
answer: '150',
hint: '设a=15x, b=15y, c=15z',
explanation: '<strong>解析:</strong>设 $a=15x, b=15y, c=15z$<br>$15^3 \\cdot xyz = 33750$ → $xyz = 10 = 1 \\times 2 \\times 5$<br>$a=15, b=30, c=75$<br>$\\text{LCM} = 15 \\times 10 = <strong>150</strong>$'
}
]
}
},
methods: {
// 语音播报
speak(text) {
if (window.speechSynthesis) window.speechSynthesis.cancel();
const isWeChat = /MicroMessenger/i.test(navigator.userAgent);
if (isWeChat) {
let audio = document.getElementById('tts-audio');
if (!audio) {
audio = document.createElement('audio'); audio.id = 'tts-audio'; audio.style.display = 'none';
document.body.appendChild(audio);
}
const url = `https://www.xinghuo.tv/wp-content/themes/xinghuo-tv/tts.php?text=${encodeURIComponent(text)}&t=${Date.now()}`;
audio.src = url;
audio.play().catch(e => { if(window.WeixinJSBridge) window.WeixinJSBridge.invoke('getNetworkType',{},()=>audio.play()); });
} else {
if (window.speechSynthesis) {
const u = new SpeechSynthesisUtterance(text); u.lang = 'zh-CN'; u.rate = 0.9;
window.speechSynthesis.speak(u);
}
}
},
speakProduct() {
this.speak('乘积关系是最重要的公式:两个数的乘积等于它们的最大公约数乘以最小公倍数。知道三个,就能求第四个!');
},
speakCoprime() {
this.speak('互质关系很特殊:如果两个数互质,也就是最大公约数是1,那么它们的最小公倍数就等于两数的乘积。相邻自然数一定互质,两个不同的质数也一定互质。');
},
speakMultiple() {
this.speak('倍数关系最简单:如果A是B的倍数,那么它们的最大公约数就是较小的数B,最小公倍数就是较大的数A。因为大数已经包含了小数。');
},
speakScale() {
this.speak('同倍缩放是计算大数的神器:两个数同时乘以或除以同一个数,它们的最大公约数和最小公倍数也会同步变化。算大数时先缩小,算完再放大回去!');
},
// 页面切换
switchPage(page) {
if (window.speechSynthesis) window.speechSynthesis.cancel();
this.currentPage = page;
window.scrollTo(0, 0);
this.$nextTick(() => this.renderMath());
},
// 渲染数学公式
renderMath() {
if (typeof renderMathInElement !== 'undefined') {
setTimeout(() => {
renderMathInElement(document.body, {
delimiters: [
{left: '$$', right: '$$', display: true},
{left: '$', right: '$', display: false}
],
throwOnError: false
});
}, 100);
}
},
// 乘积关系动画
animateProduct() {
if (typeof gsap === 'undefined') return;
const container = document.getElementById('product-demo');
container.innerHTML = '';
container.style.flexDirection = 'column';
const createBox = (text, bg, delay) => {
const box = document.createElement('div');
box.className = 'number-box';
box.textContent = text;
box.style.background = bg;
container.appendChild(box);
gsap.fromTo(box,
{opacity: 0, scale: 0},
{opacity: 1, scale: 1, duration: 0.5, delay}
);
return box;
};
const createOp = (text, delay) => {
const op = document.createElement('div');
op.className = 'operator';
op.textContent = text;
container.appendChild(op);
gsap.fromTo(op,
{opacity: 0},
{opacity: 1, duration: 0.3, delay}
);
return op;
};
// 第一行容器
const row1 = document.createElement('div');
row1.style.cssText = 'display: flex; justify-content: center; align-items: center; gap: 15px; flex-wrap: wrap;';
container.appendChild(row1);
// 临时将元素添加到row1
const oldAppend = container.appendChild;
container.appendChild = (el) => {
if (el.className === 'number-box' || el.className === 'operator') {
row1.appendChild(el);
} else {
oldAppend.call(container, el);
}
};
// A × B = 216
createBox('12', '#3B82F6', 0);
createOp('×', 0.6);
createBox('18', '#3B82F6', 1.2);
createOp('=', 1.8);
createBox('216', '#8B5CF6', 2.4);
// 恢复appendChild
container.appendChild = oldAppend;
// 3秒后显示质因数分解
setTimeout(() => {
const separator1 = document.createElement('div');
separator1.style.cssText = 'width: 100%; height: 1px; background: rgba(255,255,255,0.2); margin: 15px 0;';
container.appendChild(separator1);
gsap.fromTo(separator1, {opacity: 0}, {opacity: 1, duration: 0.3});
// 质因数分解说明
const factorSection = document.createElement('div');
factorSection.style.cssText = 'width: 100%; color: white; font-size: 12px; line-height: 1.6; margin: 10px 0;';
factorSection.innerHTML = `
<div style="display: flex; justify-content: space-around; gap: 10px; margin: 10px 0;">
<div style="flex: 1; text-align: center; background: rgba(59, 130, 246, 0.15); padding: 10px; border-radius: 8px; border: 1px solid #3B82F6;">
<div style="color: #60A5FA; font-weight: bold; margin-bottom: 5px; font-size: 11px;">12的分解</div>
<div style="font-size: 13px; font-weight: bold;">12 = 2² × 3</div>
</div>
<div style="flex: 1; text-align: center; background: rgba(59, 130, 246, 0.15); padding: 10px; border-radius: 8px; border: 1px solid #3B82F6;">
<div style="color: #60A5FA; font-weight: bold; margin-bottom: 5px; font-size: 11px;">18的分解</div>
<div style="font-size: 13px; font-weight: bold;">18 = 2 × 3²</div>
</div>
</div>
`;
container.appendChild(factorSection);
gsap.fromTo(factorSection, {opacity: 0, y: -10}, {opacity: 1, y: 0, duration: 0.5, delay: 0.3});
// 原理说明
setTimeout(() => {
const principle = document.createElement('div');
principle.style.cssText = 'width: 100%; background: rgba(16, 185, 129, 0.15); padding: 12px; border-radius: 8px; border: 1px solid #10B981; margin: 10px 0;';
principle.innerHTML = `
<div style="color: #34D399; font-weight: bold; margin-bottom: 8px; font-size: 12px;">📐 质因数视角</div>
<div style="font-size: 11px; line-height: 1.6; color: #CBD5E1;">
<strong style="color: #10B981;">GCD(12,18)</strong> = 2¹ × 3¹ = <strong>6</strong> (取最小指数)<br>
<strong style="color: #F59E0B;">LCM(12,18)</strong> = 2² × 3² = <strong>36</strong> (取最大指数)
</div>
`;
container.appendChild(principle);
gsap.fromTo(principle, {opacity: 0, y: -10}, {opacity: 1, y: 0, duration: 0.5});
}, 800);
setTimeout(() => {
const separator2 = document.createElement('div');
separator2.style.cssText = 'width: 100%; height: 1px; background: rgba(255,255,255,0.2); margin: 15px 0;';
container.appendChild(separator2);
gsap.fromTo(separator2, {opacity: 0}, {opacity: 1, duration: 0.3});
// 第二行容器
const row2 = document.createElement('div');
row2.style.cssText = 'display: flex; justify-content: center; align-items: center; gap: 15px; flex-wrap: wrap;';
container.appendChild(row2);
// 临时修改appendChild
const oldAppend2 = container.appendChild;
container.appendChild = (el) => {
if (el.className === 'number-box' || el.className === 'operator') {
row2.appendChild(el);
} else {
oldAppend2.call(container, el);
}
};
// GCD × LCM = 216
createBox('6', '#10B981', 0.5);
createOp('×', 1.1);
createBox('36', '#F59E0B', 1.7);
createOp('=', 2.3);
createBox('216', '#8B5CF6', 2.9);
// 恢复appendChild
container.appendChild = oldAppend2;
setTimeout(() => {
document.getElementById('product-text').textContent = '✓ 验证成功!12×18 = 6×36 = 216';
}, 3500);
}, 1500);
}, 3000);
document.getElementById('product-text').textContent = '例子:A=12,B=18,验证 A×B = GCD×LCM';
},
// 互质关系动画
animateCoprime() {
if (typeof gsap === 'undefined') return;
const container = document.getElementById('coprime-demo');
container.innerHTML = '';
container.style.flexDirection = 'column';
const createBox = (text, bg, delay) => {
const box = document.createElement('div');
box.className = 'number-box';
box.textContent = text;
box.style.background = bg;
container.appendChild(box);
gsap.fromTo(box,
{opacity: 0, scale: 0},
{opacity: 1, scale: 1, duration: 0.5, delay}
);
return box;
};
const createOp = (text, delay) => {
const op = document.createElement('div');
op.className = 'operator';
op.textContent = text;
container.appendChild(op);
gsap.fromTo(op,
{opacity: 0},
{opacity: 1, duration: 0.3, delay}
);
return op;
};
// 第一行容器
const row1 = document.createElement('div');
row1.style.cssText = 'display: flex; justify-content: center; align-items: center; gap: 15px; flex-wrap: wrap;';
container.appendChild(row1);
const oldAppend = container.appendChild;
container.appendChild = (el) => {
if (el.className === 'number-box' || el.className === 'operator') {
row1.appendChild(el);
} else {
oldAppend.call(container, el);
}
};
// 7 和 9 互质
createBox('7', '#3B82F6', 0);
createOp('和', 0.6);
createBox('9', '#3B82F6', 1.2);
createOp('互质', 1.8);
container.appendChild = oldAppend;
// 2.5秒后显示质因数分解
setTimeout(() => {
const separator1 = document.createElement('div');
separator1.style.cssText = 'width: 100%; height: 1px; background: rgba(255,255,255,0.2); margin: 15px 0;';
container.appendChild(separator1);
gsap.fromTo(separator1, {opacity: 0}, {opacity: 1, duration: 0.3});
// 质因数分解说明
const factorSection = document.createElement('div');
factorSection.style.cssText = 'width: 100%; color: white; font-size: 12px; line-height: 1.6; margin: 10px 0;';
factorSection.innerHTML = `
<div style="display: flex; justify-content: space-around; gap: 10px; margin: 10px 0;">
<div style="flex: 1; text-align: center; background: rgba(59, 130, 246, 0.15); padding: 10px; border-radius: 8px; border: 1px solid #3B82F6;">
<div style="color: #60A5FA; font-weight: bold; margin-bottom: 5px; font-size: 11px;">7的分解</div>
<div style="font-size: 13px; font-weight: bold;">7 = 7¹</div>
<div style="font-size: 10px; color: #93C5FD; margin-top: 3px;">(质数)</div>
</div>
<div style="flex: 1; text-align: center; background: rgba(59, 130, 246, 0.15); padding: 10px; border-radius: 8px; border: 1px solid #3B82F6;">
<div style="color: #60A5FA; font-weight: bold; margin-bottom: 5px; font-size: 11px;">9的分解</div>
<div style="font-size: 13px; font-weight: bold;">9 = 3²</div>
<div style="font-size: 10px; color: #93C5FD; margin-top: 3px;">(合数)</div>
</div>
</div>
`;
container.appendChild(factorSection);
gsap.fromTo(factorSection, {opacity: 0, y: -10}, {opacity: 1, y: 0, duration: 0.5, delay: 0.3});
// 互质原理说明
setTimeout(() => {
const principle = document.createElement('div');
principle.style.cssText = 'width: 100%; background: rgba(251, 191, 36, 0.15); padding: 12px; border-radius: 8px; border: 1px solid #F59E0B; margin: 10px 0;';
principle.innerHTML = `
<div style="color: #FCD34D; font-weight: bold; margin-bottom: 8px; font-size: 12px;">🤝 互质原理</div>
<div style="font-size: 11px; line-height: 1.6; color: #CBD5E1;">
7和9<strong style="color: #FCD34D;">没有公共质因数</strong><br>
所以 GCD(7,9) = 1,LCM(7,9) = 7 × 9
</div>
`;
container.appendChild(principle);
gsap.fromTo(principle, {opacity: 0, y: -10}, {opacity: 1, y: 0, duration: 0.5});
}, 800);
setTimeout(() => {
const separator2 = document.createElement('div');
separator2.style.cssText = 'width: 100%; height: 1px; background: rgba(255,255,255,0.2); margin: 15px 0;';
container.appendChild(separator2);
gsap.fromTo(separator2, {opacity: 0}, {opacity: 1, duration: 0.3});
const row2 = document.createElement('div');
row2.style.cssText = 'display: flex; justify-content: center; align-items: center; gap: 15px; flex-wrap: wrap;';
container.appendChild(row2);
const oldAppend2 = container.appendChild;
container.appendChild = (el) => {
if (el.className === 'number-box' || el.className === 'operator') {
row2.appendChild(el);
} else {
oldAppend2.call(container, el);
}
};
// 7 × 9 = 63
createBox('7', '#10B981', 0.5);
createOp('×', 1.1);
createBox('9', '#10B981', 1.7);
createOp('=', 2.3);
createBox('63', '#F59E0B', 2.9);
container.appendChild = oldAppend2;
setTimeout(() => {
document.getElementById('coprime-text').textContent = '✓ LCM(7, 9) = 7 × 9 = 63(互质直接相乘)';
}, 3500);
}, 1500);
}, 2500);
document.getElementById('coprime-text').textContent = '互质例子:7和9,GCD=1';
},
// 倍数关系动画
animateMultiple() {
if (typeof gsap === 'undefined') return;
const container = document.getElementById('multiple-demo');
container.innerHTML = '';
const createBox = (text, bg, delay, size = 60) => {
const box = document.createElement('div');
box.className = 'number-box';
box.textContent = text;
box.style.background = bg;
box.style.width = size + 'px';
box.style.height = size + 'px';
container.appendChild(box);
gsap.fromTo(box,
{opacity: 0, scale: 0},
{opacity: 1, scale: 1, duration: 0.5, delay}
);
return box;
};
const createOp = (text, delay) => {
const op = document.createElement('div');
op.className = 'operator';
op.textContent = text;
container.appendChild(op);
gsap.fromTo(op,
{opacity: 0},
{opacity: 1, duration: 0.3, delay}
);
return op;
};
// 6 × 3 = 18
createBox('6', '#3B82F6', 0, 50);
createOp('×3=', 0.6);
createBox('18', '#8B5CF6', 1.2, 80);
setTimeout(() => {
const text = document.createElement('div');
text.style.cssText = 'color: #FCD34D; font-size: 16px; font-weight: bold; text-align: center; width: 100%; margin-top: 20px;';
text.innerHTML = 'GCD = 6(小的)<br>LCM = 18(大的)';
container.appendChild(text);
gsap.fromTo(text, {opacity: 0}, {opacity: 1, duration: 0.5});
document.getElementById('multiple-text').textContent = '18是6的3倍,所以GCD=6,LCM=18';
}, 2000);
document.getElementById('multiple-text').textContent = '倍数关系:18 = 6 × 3';
},
// 同倍缩放动画
animateScale() {
if (typeof gsap === 'undefined') return;
const container = document.getElementById('scale-demo');
container.innerHTML = '';
const steps = [
{eq: '原问题:GCD(1200, 1600) = ?', exp: '大数不好算'},
{eq: '提取公因数:1200 = 12 × 100,1600 = 16 × 100', exp: '发现都是100的倍数'},
{eq: '缩小100倍:GCD(12, 16) = ?', exp: '先算小数'},
{eq: 'GCD(12, 16) = 4', exp: '计算结果'},
{eq: '放大100倍:4 × 100 = <span class="calc-highlight">400</span>', exp: '还原答案'}
];
steps.forEach((step, i) => {
const div = document.createElement('div');
div.className = 'calc-step';
div.innerHTML = `
<div class="calc-equation">${step.eq}</div>
<div class="calc-explanation">${step.exp}</div>
`;
container.appendChild(div);
gsap.fromTo(div,
{opacity: 0, y: 20},
{
opacity: 1,
y: 0,
duration: 0.5,
delay: i * 1.5,
onStart: () => {
if (i > 0) {
for (let j = 0; j < i; j++) {
container.children[j].classList.remove('active');
}
}
div.classList.add('active');
document.getElementById('scale-text').textContent = `第${i+1}步:${step.exp}`;
}
}
);
});
document.getElementById('scale-text').textContent = '点击按钮开始演示';
this.$nextTick(() => this.renderMath());
},
// 例题切换
switchExample(index) {
this.exampleIndex = index;
this.$nextTick(() => this.renderMath());
},
nextExampleStep(index) {
if (this.exampleSteps[index] < this.classicExamples[index].steps.length - 1) {
this.exampleSteps[index]++;
this.$nextTick(() => this.renderMath());
}
},
prevExampleStep(index) {
if (this.exampleSteps[index] > 0) {
this.exampleSteps[index]--;
}
},
resetExampleStep(index) {
this.exampleSteps[index] = 0;
},
// 练习题
checkPracticeAnswer() {
if (this.practiceAnswered) return;
const correctAnswer = this.practiceQuestions[this.currentPracticeIndex].answer.toLowerCase().trim();
const userAnswer = this.userAnswer.toLowerCase().trim().replace(/\s+/g, '');
const correct = userAnswer === correctAnswer ||
userAnswer === correctAnswer.replace(/\*/g, '') ||
userAnswer === correctAnswer.replace('*', 'x');
this.practiceAnswered = true;
this.isPracticeCorrect = correct;
if (correct) {
this.practiceScore += 10;
}
this.$nextTick(() => this.renderMath());
},
nextPractice() {
if (this.currentPracticeIndex < 9) {
this.currentPracticeIndex++;
this.practiceAnswered = false;
this.userAnswer = '';
this.$nextTick(() => this.renderMath());
} else {
this.practiceDone = true;
}
},
// 杯赛真题
checkOlympiadAnswer() {
if (this.olympiadAnswered) return;
const correctAnswer = this.olympiadQuestions[this.currentOlympiadIndex].answer.toLowerCase().trim();
const userAnswer = this.userOlympiadAnswer.toLowerCase().trim().replace(/\s+/g, '');
const correct = userAnswer === correctAnswer ||
userAnswer === correctAnswer.replace(',', '或') ||
userAnswer === correctAnswer.replace(',', ' ');
this.olympiadAnswered = true;
this.isOlympiadCorrect = correct;
if (correct) {
this.olympiadScore += 10;
}
this.$nextTick(() => this.renderMath());
},
nextOlympiad() {
if (this.currentOlympiadIndex < 9) {
this.currentOlympiadIndex++;
this.olympiadAnswered = false;
this.userOlympiadAnswer = '';
this.$nextTick(() => this.renderMath());
} else {
this.olympiadDone = true;
}
}
},
mounted() {
this.renderMath();
}
}).mount('#app');
</script>
</body>
</html>
💡 这段代码完全由 claude 生成。
登录后可复制完整代码