Qwen3 RL-Based Reasoning Fine-Tuning on MATH-500

This notebook demonstrates how to fine-tune Qwen3-1.7B for mathematical reasoning on the MATH-500 benchmark using Group Relative Policy Optimization (GRPO).

Dataset: MATH-500

MATH-500 is a curated subset of 500 problems from the full MATH benchmark, covering competition-level mathematics in 7 subjects (algebra, geometry, number theory, etc.). Each example contains: - problem: the mathematical question. - solution: the reference solution (used for answer extraction only, not shown to the model during training). - answer: the final answer extracted from the solution. - subject / level: metadata about the problem domain and difficulty.

Install Dependencies

# Install required libraries
# transformers : Hugging Face model hub and training utilities
# datasets     : easy dataset loading and preprocessing
# peft         : parameter-efficient fine-tuning (LoRA)
# bitsandbytes : 4-bit / 8-bit quantization kernels
# trl          : GRPOTrainer for RL-based fine-tuning
# accelerate   : distributed / mixed-precision training
!pip install -q transformers datasets peft bitsandbytes trl accelerate
# for symbolic answer comparison
!pip install -q latex2sympy2 sympy

Import Modules

import re
import torch
# Hugging Face libraries
from datasets import load_dataset
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
# LoRA / PEFT
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
# RL trainer
from trl import GRPOConfig, GRPOTrainer

Load the MATH-500 Dataset

# Load the 'test' split of MATH-500 from the Hugging Face Hub
dataset = load_dataset("HuggingFaceH4/MATH-500", split="test")

# MATH-500 is a fixed subset of 500 problems
dataset = dataset.select(range(500))
# Print the dataset and the column names
print(dataset)
print(dataset.column_names)
Dataset({
    features: ['problem', 'solution', 'answer', 'subject', 'level', 'unique_id'],
    num_rows: 500
})
['problem', 'solution', 'answer', 'subject', 'level', 'unique_id']
# Inspect the first sample
sample = dataset[0]
print("Subject:", sample['subject'])
print("Level:", sample['level'])
print("Problem:", sample['problem'])
print("Solution:", sample['solution'][:800])
Subject: Precalculus
Level: 2
Problem: Convert the point $(0,3)$ in rectangular coordinates to polar coordinates.  Enter your answer in the form $(r,\theta),$ where $r > 0$ and $0 \le \theta < 2 \pi.$
Solution: We have that $r = \sqrt{0^2 + 3^2} = 3.$  Also, if we draw the line connecting the origin and $(0,3),$ this line makes an angle of $\frac{\pi}{2}$ with the positive $x$-axis.

[asy]
unitsize(0.8 cm);

draw((-0.5,0)--(3.5,0));
draw((0,-0.5)--(0,3.5));
draw(arc((0,0),3,0,90),red,Arrow(6));

dot((0,3), red);
label("$(0,3)$", (0,3), W);
dot((3,0), red);
[/asy]

Therefore, the polar coordinates are $\boxed{\left( 3, \frac{\pi}{2} \right)}.$

Reward Functions

GRPO learns by sampling multiple responses for each prompt, then using scalar reward signals to rank them. We define two complementary reward functions:

Reward - correctness_reward: +2.0 if the final answer matches the reference, 0.0 otherwise. - format_reward: +0.5 if the model wraps its reasoning in <think>…</think> tags.

These rewards encourage the model to produce correct answers, and show its reasoning explicitly.

def extract_boxed_answer(text: str) -> str | None:
    """Extract the content of the answer in \\boxed{}."""
    key = r"\boxed{"
    results = []
    idx = 0
    while True:
        start = text.find(key, idx)
        if start == -1:
            break
        # Walk forward counting braces to find the matching closing brace
        depth = 1
        i = start + len(key)
        while i < len(text) and depth > 0:
            if text[i] == "{":
                depth += 1
            elif text[i] == "}":
                depth -= 1
            i += 1
        results.append(text[start + len(key) : i - 1].strip())
        idx = i
    return results[-1] if results else None

def correctness_reward(prompts, completions, answer, **kwargs) -> list[float]:
    """
    Reward +2.0 if the model's boxed answer matches the reference answer,
    else 0.0.  Both answers are compared after stripping whitespace.
    """
    rewards = []
    for completion, ref in zip(completions, answer):
        # completions is a list of lists (one list of messages per sample)
        response_text = completion[0]["content"]
        predicted = extract_boxed_answer(response_text)
        ref_clean  = ref.strip()
        if predicted is not None and predicted == ref_clean:
            rewards.append(2.0)
        else:
            rewards.append(0.0)
    return rewards

def format_reward(prompts, completions, **kwargs) -> list[float]:
    """
    Reward +0.5 if the response contains explicit <think>…</think> reasoning
    tags, encouraging the model to show its work.
    """
    rewards = []
    pattern = re.compile(r"<think>.*?</think>", re.DOTALL)
    for completion in completions:
        response_text = completion[0]["content"]
        rewards.append(0.5 if pattern.search(response_text) else 0.0)
    return rewards

Format the Dataset for GRPO

SYSTEM_PROMPT = (
    "You are a mathematical reasoning assistant. "
    "Think step-by-step inside <think>…</think> tags, then write your final answer "
    "inside a LaTeX \\boxed{} command."
)


def format_example(example):
    """
    Convert a MATH-500 row into the chat-message format expected by GRPOTrainer.
    GRPOTrainer expects a 'prompt' column containing a list of message dicts.
    We also keep the reference 'answer' column for the reward function.
    """
    # Extract the boxed answer from the full solution to use as ground truth
    ref_answer = extract_boxed_answer(example["solution"]) or example["solution"][-50:]

    return {
        "prompt": [
            {"role": "system",  "content": SYSTEM_PROMPT},
            {"role": "user",    "content": example["problem"]},
        ],
        "answer": ref_answer,
    }
# Apply formatting and keep only the columns GRPOTrainer needs
dataset = dataset.map(format_example, remove_columns=dataset.column_names)
# First prompt messages
for msg in dataset[0]["prompt"]:
    print(f"  [{msg['role']}] {msg['content'][:120]}")
print("Reference answer:", dataset[0]["answer"])
  [system] You are a mathematical reasoning assistant. Think step-by-step inside <think>…</think> tags, then write your final answe
  [user] Convert the point $(0,3)$ in rectangular coordinates to polar coordinates.  Enter your answer in the form $(r,\theta),$ 
Reference answer: tes are $\boxed{\left( 3, \frac{\pi}{2} \right)}.$

Quantization Configuration (4-bit QLoRA)

# BitsAndBytes configuration
bnb_config = BitsAndBytesConfig(
    # Load the model using 4-bit precision
    load_in_4bit=True,
    # Quantization type (fp4 or nf4)
    # nf4 is "normalized float 4" format, uses an asymmetric quantization scheme with 4-bit precision
    # optimized for normally distributed weights (better than fp4 for neural networks)
    bnb_4bit_quant_type="nf4",
    # Compute dtype for 4-bit models
    bnb_4bit_compute_dtype=torch.bfloat16,
    # Use double quantization for 4-bit models
    # Double quantization applies further quantization to the quantization constants
    bnb_4bit_use_double_quant=True,
)

Load the Base Model and Tokenizer

# Load Qwen3-1.7B
model_name = "Qwen/Qwen3-1.7B"
# Load Qwen3 model from Hugging Face
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    # Apply 4-bit quantization
    quantization_config=bnb_config,
    # Don't cache key/value states during training
    use_cache=False,
    # Load the entire model on the GPU if available
    device_map="auto",
    # Enable Qwen3's native thinking mode
    attn_implementation="eager",
)
The tied weights mapping and config for this model specifies to tie model.embed_tokens.weight to lm_head.weight, but both are present in the checkpoints, so we will NOT tie them. You should update the config with `tie_word_embeddings=False` to silence this warning
# Prepare model for k-bit (QLoRA) training
model = prepare_model_for_kbit_training(model)
# Load tokenizer
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)

# Ensure pad token is set
if tokenizer.pad_token is None:
    tokenizer.pad_token = tokenizer.eos_token

# Pad on the left for decoder-only generation
tokenizer.padding_side = "left"
# Print the vocabulary size
print(tokenizer.vocab_size)
151643

Apply LoRA (Parameter-Efficient Fine-Tuning)

# LoRA configuration
lora_config = LoraConfig(
    # LoRA rank dimension (controls capacity of LoRA layers)
    r=16,
    # Scaling parameter for LoRA updates (higher alpha increases contribution of LoRA weights)
    lora_alpha=64,
    # Dropout rate for LoRA layers
    lora_dropout=0.05,
    # Specifies whether to add bias in LoRA layers
    bias="none",
    # "CAUSAL_LM" indicates that LoRA is applied for causal language modeling
    task_type="CAUSAL_LM",
    # Qwen3 attention projection names
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj",
                    "gate_proj", "up_proj", "down_proj"],
)
# Wrap the model with LoRA adapters
model = get_peft_model(model, lora_config)

# Print the fraction of trainable parameters with LoRA
model.print_trainable_parameters()
trainable params: 17,432,576 || all params: 2,049,172,480 || trainable%: 0.8507

GRPO Training Configuration

GRPO (Group Relative Policy Optimization) is an RL algorithm designed for LLMs. For each prompt it: 1. Samples multiple completions from the current policy. 2. Scores each with the reward functions. 3. Normalises rewards within the group to compute advantages. 4. Updates the policy to increase the probability of high-reward completions, with a KL penalty to stay close to the reference policy.

# GRPO training configuration
grpo_config = GRPOConfig(
    # Output directory where the model predictions and checkpoints will be stored
    output_dir="./qwen3-math-grpo",
    # Total training steps
    max_steps=250,
    # Number of prompts processed per optimisation step
    per_device_train_batch_size=2,
    # Gradient accumulation to simulate a larger effective batch
    gradient_accumulation_steps=4,
    # Number of response samples drawn per prompt during GRPO rollout
    num_generations=4,
    # Maximum tokens to generate per completion during rollout
    max_completion_length=512,
    # Learning rate
    learning_rate=5e-6,
    # Optimizer
    optim="paged_adamw_8bit",
    # Mixed-precision
    bf16=False,
    fp16=False,
    # KL penalty coefficient, keeps policy from diverging too far from reference
    beta=0.04,
    # Log every N steps
    logging_steps=10,
    # Save a checkpoint every N steps
    save_steps=50,
    # Disable external reporting
    report_to="none",
)

RL Training with GRPOTrainer

# GRPOTrainer handles the full RL loop
trainer = GRPOTrainer(
    model=model,
    processing_class=tokenizer,
    reward_funcs=[correctness_reward, format_reward],
    args=grpo_config,
    train_dataset=dataset,
)
# Start RL training
trainer.train()
The tokenizer has new PAD/BOS/EOS tokens that differ from the model config and generation config. The model config and generation config were aligned accordingly, being updated with the tokenizer's values. Updated tokens: {'bos_token_id': None, 'pad_token_id': 151643}.
Passing `generation_config` together with generation-related arguments=({'disable_compile'}) is deprecated and will be removed in future versions. Please pass either a `generation_config` object OR all generation parameters explicitly, but not both.
[ 45/250 1:56:06 < 9:13:30, 0.01 it/s, Epoch 0.18/1]
Step Training Loss
10 0.000000
20 0.000005
30 0.000011
40 0.000010

[250/250 11:08:29, Epoch 1/1]
Step Training Loss
10 0.000000
20 0.000005
30 0.000011
40 0.000010
50 0.000011
60 0.000014
70 0.000020
80 0.001136
90 0.000028
100 0.000036
110 0.000031
120 0.000030
130 0.000035
140 0.000039
150 0.000036
160 0.000143
170 0.000046
180 0.000046
190 0.000038
200 0.000050
210 0.000039
220 0.000058
230 0.000032
240 0.000037
250 0.000034

TrainOutput(global_step=250, training_loss=7.859855078277178e-05, metrics={'train_runtime': 40279.4771, 'train_samples_per_second': 0.05, 'train_steps_per_second': 0.006, 'total_flos': 0.0, 'train_loss': 7.859855078277178e-05})

Inference with the Fine-Tuned Model

# Set model to inference mode
model.eval()
model.config.use_cache = True
from IPython.display import display, Markdown

# Function for generating responses to math problems
def solve_math(problem: str, max_new_tokens: int = 2048) -> None:
    """Generate a step-by-step solution for a given maths problem."""
    messages = [
        {"role": "system", "content": SYSTEM_PROMPT},
        {"role": "user",   "content": problem},
    ]

    # Apply Qwen3 chat template
    inputs = tokenizer.apply_chat_template(
        messages,
        return_tensors="pt",
        add_generation_prompt=True,
        return_dict=True,
    ).to(model.device)

    with torch.no_grad():
        outputs = model.generate(
            **inputs,
            max_new_tokens=max_new_tokens,
            do_sample=True,
            temperature=0.6,
            top_p=0.95,
            repetition_penalty=1.05,
            eos_token_id=tokenizer.eos_token_id,
        )

    # Decode only the newly generated tokens and skip the prompt
    generated_ids = outputs[0][inputs["input_ids"].shape[1]:]
    response = tokenizer.decode(generated_ids, skip_special_tokens=True).strip()

    # Render as formatted Markdown/LaTeX
    display(Markdown(response))

    # Extract the final answer
    boxed = extract_boxed_answer(response)
    print("Extracted answer:", boxed if boxed else "(no \\boxed{} found)")
# Example 1: algebra
solve_math("Solve for x: 3x² - 12x + 9 = 0")

Okay, let’s see. I need to solve the quadratic equation 3x² - 12x + 9 = 0. Hmm, where do I start? Well, first, maybe I can simplify this equation by dividing all terms by 3 to make the coefficients smaller. Let me try that.

So, dividing each term by 3: 3x² divided by 3 is x², -12x divided by 3 is -4x, and 9 divided by 3 is 3. So the equation simplifies to x² - 4x + 3 = 0. That looks simpler. Now, maybe I can factor this quadratic. Let me check.

Looking for two numbers that multiply to 3 (the constant term) and add up to -4 (the coefficient of the x term). Wait, the numbers would have to be factors of 3. Let’s think… factors of 3 are 1 and 3. But 1 and 3 add up to 4, which is positive. Since the middle term is -4x, both numbers should be negative. So -1 and -3. Yes, -1 times -3 is 3, and -1 plus -3 is -4. Perfect!

So the quadratic factors as (x - 1)(x - 3) = 0. Wait, let me check that. Expanding (x - 1)(x - 3): x² - 3x - x + 3 = x² - 4x + 3. Yep, that matches. So the solutions are x = 1 and x = 3.

But wait, let me make sure I didn’t make any mistakes. Let me verify by plugging them back into the original equation. For x = 1: 3(1)^2 -12(1) +9 = 3 -12 +9 = 0. Correct. For x = 3: 3(9) -12(3) +9 = 27 -36 +9 = 0. Also correct.

Alternatively, I could use the quadratic formula. The original equation was 3x² -12x +9 = 0. So a = 3, b = -12, c = 9. The quadratic formula is x = [-b ± sqrt(b² - 4ac)]/(2a). Let’s compute the discriminant first: b² -4ac = (-12)^2 -439 = 144 - 108 = 36. Then sqrt(36) is 6. So x = [12 ±6]/6. That gives (12+6)/6 = 18/6 = 3, and (12-6)/6 = 6/6 = 1. So same answers.

So both methods give x = 1 and x = 3. Therefore, the solutions are 1 and 3.

Wait, but the original equation after simplifying was x² -4x +3 = 0, which factors to (x-1)(x-3)=0. Yep, same result. So I think that’s it. The answer should be x = 1 and x = 3.

I don’t think there are any other solutions because it’s a quadratic equation, which can have at most two real roots. Since we found two, and they check out, that’s all. So the solution set is {1, 3}.

To solve the quadratic equation $ 3x^2 - 12x + 9 = 0 $, we begin by simplifying the equation:

\[ \frac{3x^2 - 12x + 9}{3} = 0 \quad \Rightarrow \quad x^2 - 4x + 3 = 0 \]


Step 1: Factor the Simplified Equation

We now focus on factoring $ x^2 - 4x + 3 $. We look for two numbers that multiply to $ 3 $ (the constant term) and add up to $ -4 $ (the coefficient of $ x $).

These numbers are $ -1 $ and $ -3 $. Thus, the equation factors as:

\[ x^2 - 4x + 3 = (x - 1)(x - 3) \]


Step 2: Solve the Factored Equation

Setting each factor equal to zero:

\[ x - 1 = 0 \quad \Rightarrow \quad x = 1 \] \[ x - 3 = 0 \quad \Rightarrow \quad x = 3 \]


Step 3: Verification (Optional)

We can confirm by substituting the solutions back into the original equation:

  • For $ x = 1 $: $ 3(1)^2 - 12(1) + 9 = 3 - 12 + 9 = 0 $
  • For $ x = 3 $: $ 3(3)^2 - 12(3) + 9 = 27 - 36 + 9 = 0 $

Both values satisfy the equation.


Final Answer

\[ \boxed{1 \text{ and } 3} \]

Extracted answer: 1 \text{ and } 3
# Example 2: MATH-500 sample
solve_math(dataset[0]["prompt"][1]["content"])

Okay, so I need to convert the rectangular coordinate (0, 3) to polar coordinates. Let me recall the formulas for converting between rectangular and polar coordinates.

Polar coordinates are given as (r, θ), where r is the distance from the origin to the point, and θ is the angle made with the positive x-axis. The formulas to convert from rectangular (x, y) to polar (r, θ) are:

r = √(x² + y²)

θ = arctan(y/x)

But wait, I need to be careful with θ here because arctan(y/x) can have multiple solutions depending on the quadrant. Also, since the original point is (0, 3), which is on the y-axis. Let me visualize this. The point (0, 3) is straight up along the y-axis. So, if I plot that on the coordinate plane, it’s 3 units above the origin.

So, let’s compute r first. Using the formula r = √(x² + y²). Here, x is 0 and y is 3. Plugging those values in:

r = √(0² + 3²) = √(0 + 9) = √9 = 3. Okay, that seems straightforward. So r is 3.

Now, θ. The formula is θ = arctan(y/x). But here, x is 0 and y is 3. So, plugging those in:

θ = arctan(3/0). Wait, division by zero? That’s undefined. Hmm. What does that mean?

Well, arctan of something divided by zero… Well, when x is 0, the line x=0 is the y-axis. The angle θ for a point on the y-axis is either π/2 or -π/2, right? Because the y-axis is perpendicular to the x-axis. So, if you’re on the positive y-axis, the angle is π/2 radians (which is 90 degrees), and if it’s on the negative y-axis, it’s -π/2 or 3π/2.

But since our point is (0, 3), which is on the positive y-axis. So θ should be π/2. However, I need to make sure that the arctan function isn’t giving me an error here. Since arctan(3/0) is undefined, but we know that the angle is π/2. So maybe θ is π/2.

But let me think again. Sometimes, when dealing with arctan, there’s a need to consider the quadrant. But since x is 0 and y is positive, the point is on the positive y-axis, which is the same as the vertical line. So θ is π/2.

Alternatively, sometimes people use the formula θ = arctan(y/x) but with adjustments for the quadrant. But in this case, since x is 0, the arctangent would be undefined, but we know the actual angle is π/2. So maybe θ is π/2.

Therefore, the polar coordinates are (3, π/2). Let me check if that makes sense. If we have r = 3 and θ = π/2, then converting back to rectangular coordinates: x = r cos θ = 3 cos(π/2) = 3 * 0 = 0. y = r sin θ = 3 sin(π/2) = 3 * 1 = 3. Yep, that gives us (0, 3), which matches the original point.

So, that seems correct. Therefore, the polar coordinates are (3, π/2).

Wait, but just to make sure there isn’t any other possible angle. For example, sometimes when you have points on the axes, the angle is considered as π/2 or 3π/2, depending on the direction. Since our point is on the positive y-axis, θ is π/2. So that’s correct.

Another way to think about it: the angle θ is measured from the positive x-axis. Since the point is on the y-axis, θ is π/2. So that’s the standard position angle.

I don’t think there’s any other possibility here. So the answer should be (3, π/2).

Final Answer The polar coordinates are .

To convert the rectangular coordinate \((0, 3)\) into polar coordinates \((r, \theta)\), we apply the standard conversion formulas:

  • $ r = $
  • $ = () $

Step 1: Calculate $ r $

Given: - $ x = 0 $ - $ y = 3 $

\[ r = \sqrt{0^2 + 3^2} = \sqrt{9} = 3 \]


Step 2: Calculate $ $

\[ \theta = \arctan\left(\frac{3}{0}\right) \]

This results in an undefined value due to division by zero. However, geometrically, the point \((0, 3)\) lies on the positive y-axis, which corresponds to an angle of \(\frac{\pi}{2}\) radians (or 90°) from the positive x-axis.


Final Result

Thus, the polar coordinates of the point \((0, 3)\) are:

\[ \boxed{(3, \frac{\pi}{2})} \]

Extracted answer: (3, \frac{\pi}{2})
# Example 3: number theory
solve_math("What is the remainder when 7^{100} is divided by 5?")

Okay, so I need to find the remainder when 7^100 is divided by 5. Let me think about how to approach this.

First, I remember that when dealing with remainders, especially with large exponents, modular arithmetic can be helpful. Since we’re dividing by 5, maybe I can use properties of modular arithmetic to simplify this problem.

Let me recall Euler’s theorem or Fermat’s little theorem. Fermat’s little theorem states that if p is a prime number and a is not a multiple of p, then a^(p-1) ≡ 1 mod p. Here, p is 5, which is prime, and 7 is not a multiple of 5. So, applying Fermat’s little theorem here, 7^4 ≡ 1 mod 5. Wait, because p-1 is 4, so 7^4 ≡ 1 mod 5. That means that 7^4 is congruent to 1 when divided by 5.

So, if I can express 7^100 in terms of powers of 7^4, maybe I can simplify it. Let me check. Since 100 divided by 4 is 25, so 7^100 = (74)25. Then, using Fermat’s theorem, each 7^4 is 1 mod 5, so (1)^25 mod 5 is 1 mod 5. Therefore, 7^100 ≡ 1 mod 5. Therefore, the remainder when 7^100 is divided by 5 is 1.

Wait, but let me verify this because sometimes there can be mistakes in the steps. Let me double-check.

First, confirm Fermat’s little theorem: 7^4 ≡ 1 mod 5. Let’s compute 7 mod 5. 7 divided by 5 is 1 with remainder 2, so 7 ≡ 2 mod 5. Therefore, 7^1 mod 5 is 2, 7^2 is 2^2=4 mod 5, 7^3 is 24=8≡3 mod 5, 7^4 is 23=6≡1 mod 5. Yes, that’s correct. So 7^4 ≡ 1 mod 5. Therefore, 7^4k ≡ 1^k ≡ 1 mod 5. So 7^100 is (74)25 ≡ 1^25 ≡ 1 mod 5. So yes, the remainder is 1.

Alternatively, maybe I can compute it step by step with smaller exponents. Let’s see. Maybe using exponentiation by squaring or something. But since the previous method seems correct, maybe that’s sufficient.

But just to make sure, let’s try another approach. Let’s compute 7 mod 5 is 2. So 7^1 = 2 mod 5. 7^2 = 2^2 = 4 mod 5. 7^3 = 7^2 * 7 = 42=8≡3 mod5. 7^4=32=6≡1 mod5. Then 75=74 7 ≡12=2 mod5. So cycle repeats every 4. Therefore, the cycle length is 4. Therefore, 7^100. Since 100 divided by 4 is 25, so the remainder is 0? Wait, no. Wait, 7^4 ≡1, so 7^4k ≡1^k=1 mod5. So 7100=(74)^25 ≡1^25=1 mod5. So same result. So the remainder is 1.

Alternatively, if I compute 7^100 mod5. Since 7≡2 mod5, so 2^100 mod5. Now, 2^4=16≡1 mod5. So 2^4k ≡1^k=1 mod5. Therefore, 2100=(24)25≡125=1 mod5. So same answer. So yes, the remainder is 1.

Therefore, the answer should be 1.

Wait, but just to make sure, maybe I can compute it with smaller exponents. For example, 7^1=2, 7^2=4, 7^3=3, 7^4=1, 7^5=2, etc. So the cycle is 4. So 7^4k+1=2, 7^4k+2=4, 7^4k+3=3, 7^4k+4=1. Therefore, 7^100 is 7^(4*25)= (74)25 ≡1^25=1 mod5. Yep, same conclusion.

Another way: 7^100 = (74)25. Since 7^4=1 mod5, then (1)^25=1 mod5. So yes.

Therefore, the remainder is indeed 1.

I think that’s thorough. I don’t see any mistakes here. So the answer is 1.

Final Answer The remainder when \(7^{100}\) is divided by 5 is .

To solve the problem of finding the remainder when \(7^{100}\) is divided by 5, we apply Fermat’s Little Theorem. This theorem states that for a prime number \(p\) and an integer \(a\) not divisible by \(p\), we have:

\[ a^{p-1} \equiv 1 \pmod{p} \]

Here, \(p = 5\) and \(a = 7\). Since \(7\) is not divisible by \(5\), we apply the theorem:

\[ 7^{5-1} = 7^4 \equiv 1 \pmod{5} \]

This implies:

\[ 7^4 \equiv 1 \pmod{5} \]

We now reduce the exponent \(100\) modulo \(4\) (since \(7^4 \equiv 1\)):

\[ 100 \div 4 = 25 \text{ remainder } 0 \]

Thus,

\[ 7^{100} = (7^4)^{25} \equiv 1^{25} \equiv 1 \pmod{5} \]


Final Result

The remainder when \(7^{100}\) is divided by 5 is:

\[ \boxed{1} \]

Extracted answer: 1