CCINP Informatique optionnelle MP 2026

Thème de l'épreuve Multiplications de grands entiers, tries, logique implicationnelle
Principaux outils utilisés diviser pour régner, arbres, déduction naturelle
Mots clefs Karatsuba, dictionnaires, Peirce (loi de)

Corrigé

 :
👈 gratuite pour tous les corrigés si tu crées un compte
👈 l'accès aux indications de tous les corrigés ne coûte que 1 € ⬅ clique ici
👈 gratuite pour tous les corrigés si tu crées un compte
- - - - - - - - - - - - - - - - - - - - - - - -
👈 gratuite pour ce corrigé si tu crées un compte
- - - - - - - - - - - - - - -

Énoncé complet

(télécharger le PDF)
                                

Énoncé obtenu par reconnaissance optique des caractères


SESSION 2026

MP7IN

ÉPREUVE MUTUALISÉE AVEC E3A-POLYTECH
ÉPREUVE SPÉCIFIQUE - FILIÈRE MP
____________________

INFORMATIQUE
Durée : 4 heures
____________________
N.B. : le candidat attachera la plus grande importance à la clarté, à la 
précision et à la concision de la rédaction.
Si un candidat est amené à repérer ce qui peut lui sembler être une erreur 
d'énoncé, il le signalera sur sa copie
et devra poursuivre sa composition en expliquant les raisons des initiatives 
qu'il a été amené à prendre.
RAPPEL DES CONSIGNES
·

·
·

Utiliser uniquement un stylo noir ou bleu foncé non effaçable pour la rédaction 
de votre composition ; d'autres
couleurs, excepté le vert, bleu clair ou turquoise, peuvent être utilisées, 
mais exclusivement pour les schémas
et la mise en évidence des résultats.
Ne pas utiliser de correcteur.
Écrire le mot FIN à la fin de votre composition.

________________________________________________________________________________

Les calculatrices sont interdites.

Le sujet est composé de trois problèmes indépendants.

1/11

PROBLÈME 1
Multiplication de grands entiers
Pour manipuler des entiers, les ordinateurs manipulent à la place des suites de 
bits encodant
ces entiers. On admet que si n est un entier naturel et b est un entier 
supérieur ou égal à 2,
il existe une décomposition de n sous la forme :
k

n=
ni bi
i=0

appelée décomposition de n en base b. Les ni sont appelés chiffres de n en base 
b et
chaque ni est dans {0, . . . , b - 1}. La base choisie de manière standard pour 
les entiers est
habituellement b = 2 et pour cette valeur de b, on appelle les chiffres des 
bits. Par ailleurs,
pour des raisons liées au matériel, on se limite à un nombre de chiffres borné, 
entre 32 et
64 sur les machines modernes.
Dans tout ce problème, on considère que la base est b = 2 et le seul langage 
utilisé
est Python.
Q1.

Quelle est la conséquence de cette contrainte matérielle sur l'ensemble des 
entiers
que peut manipuler un programme ? Est-ce le cas en Python ?

Dans ce problème, on va manipuler des listes de taille non bornée de chiffres. 
Ces listes
seront représentées par des listes Python dans lesquelles le terme de rang i 
vaudra le ième bit, ni , c'est-à-dire que les bits associés à une puissance de 
2 faibles seront en début
de liste. Par exemple [0, 1, 0, 1, 0, 1] représente l'entier 42 = 0 + 2 + 0 + 8 
+ 0 + 32.
Q2.

Donner le code d'une fonction bit_to_int(bit_lst) prenant en argument une liste
de bits et renvoyant la valeur de l'entier correspondant. Cette fonction devra 
avoir une
complexité linéaire en la taille de la liste qu'il n'est pas nécessaire de 
justifier.

Q3.

Expliquer en français les grandes lignes d'un algorithme pour réaliser la somme 
de
deux entiers représentés sous forme de listes de bits.

Q4.

Donner le code d'une fonction sum_bits(b_lst_1, b_lst_2) réalisant l'addition de
deux entiers encodés par liste de bits. Cette fonction prendra en argument deux 
listes
de bits et renverra une nouvelle liste de bits correspondant à la somme des deux
entiers encodés par les arguments. Il est interdit de convertir ces listes de 
bits en
entiers, de faire la somme avec + et de reconvertir vers une liste de bits. On 
pourra
supposer que les deux listes sont de même longueur.

Pour simplifier les opérations mettant en oeuvre deux listes de bits (addition, 
soustraction,
multiplication, etc.), on souhaite que ces deux listes soient de même taille.
Q5.

Q6.

Implémenter une fonction complement(lst_bits, size) qui complémente la liste de
bits de manière à lui donner la taille size sans changer la valeur représentée. 
Votre
programme vérifiera que l'entier size est supérieur à la taille de la liste des 
bits passée en argument et si cette assertion n'est pas vérifiée, interrompra 
l'exécution du
programme. Votre fonction ne modifiera pas la liste passée en argument, mais en
renverra une nouvelle.
Donner le code d'une fonction int_to_bit permettant d'obtenir la liste des 
chiffres de
la décomposition en base b = 2 d'un entier passé en argument. On pourra 
s'appuyer
sur la valeur de n modulo b dans l'expression de sa décomposition et regarder 
l'effet
d'une division entière de n par b avec cette expression.
2/11

On souhaite à présent réaliser la multiplication de deux entiers u et v encodés 
par des listes
de bits. On peut supposer, sans perte de généralité, que la taille k de ces 
listes est la même
et est divisible par 2, quitte à utiliser la fonction complement pour que ce 
soit le cas. On peut
s'appuyer sur la relation suivante en notant :
u=

k
2 -1

ui bi +

i=0

et :
v=

k
2 -1

k

ui bi = du + b 2 fu

i= 2k

vi bi +

i=0

on a alors :

k

k

k

vi bi = dv + b 2 fv

i= 2k

 k

 i   k

u × v =  ui b  ×  vi bi 
i=0

i=0

 k

k
-1
-1
  2

 2
k
k

i
i
i
i

ui b  ×  vi b +
vi b 
=  ui b +

i=0
i=0
i= 2k
i= 2k
(
) (
)
k
k
= d u + b 2 fu × d v + b 2 fv
k

= d u × d v + b 2 ( fu × d v + f v × d u ) + b k ( fu × f v ) .

Ce calcul assure la véracité de l'égalité :
k

u × v = du × dv + b 2 ( fu × dv + fv × du ) + bk ( fu × fv ) .

(1)

On peut donc calculer le produit u × v en :
a) décomposant les listes de bits de u et v en (du , fu ) et (dv , fv ) 
respectivement,
b) calculant récursivement les 4 produits du × dv , fu × dv , fv × du et fu × 
fv ,
k
c) faisant les multiplications par les puissances de b : b 2 ( fu × dv + fv × 
du ) et bk ( fu × fv ),
d) additionnant les trois termes obtenus pour respecter l'égalité (1).
On note C(k) la complexité de l'algorithme induit par cette méthode sur une 
liste de taille k.
On admet que les opérations a, c et d peuvent se faire linéairement en k.
Établir une équation vérifiée par C(k) et résoudre cette équation pour obtenir 
la complexité de la méthode. On pourra supposer que la taille de la liste est 
une puissance
de 2 pour ne pas se préoccuper des arrondis lors de sa division par 2 et que la 
fonction
C est croissante.
Le mathématicien soviétique Anatoly Karatsuba a proposé la relation suivante 
pour améliorer la complexité du calcul de la multiplication :

Q7.

k

u × v = du × dv + b 2 ( fu × fv + du × dv - ( fu - du ) × ( fv - dv )) + bk × 
fu × fv

(2)

On admet que cette relation est correcte.
Q8.

Combien de multiplications récursives distinctes sont nécessaires pour réaliser 
le produit u × v avec l'égalité (2) ? Donner en conséquence l'équation vérifiée 
par la complexité de cette méthode de multiplication.
3/11

On admet qu'en résolvant cette équation vérifiée par la complexité, on obtient 
une complexité temporelle en O(klog2 (3) )  O(k1,586 ), ce qui est mieux que 
l'approche précédente.

Q9.

Indiquer ce à quoi correspond la multiplication par bi d'un nombre vis-à-vis de 
sa
représentation sous forme de la liste de chiffres en base b (étape c).

Q10. Implémenter une fonction shift(lst_bits, i) qui réalise cette opération 
sur une
liste de bits passée en argument. Cette fonction renverra une nouvelle liste 
sans modifier celle passée en argument.
On considère le code Python d'une fonction karatsuba(lst1, lst2) pour réaliser 
la méthode proposée par Karatsuba.
On suppose disposer d'une fonction de somme sum_bit_lst(lst1, lst2) et de 
soustraction sub_bit_lst(lst1, lst2) qui réalisent les opérations attendues en 
temps linéaire en
la taille de leurs entrées.
def karatsuba(lst1, lst2):
n = max (len(lst1), len(lst2))
lst1 = complement(lst1, n)
lst2 = complement(lst2, n)
if n == 0:
# A : compléter ici
if n == 1:
# B : compléter ici
else:
h = n//2
d1 = lst1[0:h]
f1 = lst1[h:]
d2 = lst2[0:h]
f2 = lst2[h:]
# C : compléter ici

Q11. Compléter les parties A, B et C du code proposé pour qu'il implémente la 
méthode
de Karatsuba. Plusieurs lignes peuvent être nécessaires pour compléter certaines
parties.

PROBLÈME 2
Ensembles de mots implémentés par tries
On s'intéresse dans ce problème à l'implémentation de structures permettant de 
représenter
des ensembles de mots. Ce type de structure peut être utilisé pour la 
correction orthographique -- si un mot n'est pas dans l'ensemble des mots 
connus, il y a probablement une
faute -- ou bien l'auto-complétion : s'il existe un mot dans notre ensemble qui 
commence
comme celui qui vient d'être tapé, on le propose pour compléter.
Q12. Citer deux structures au programme pour implémenter un dictionnaire.
Q13. Comment pourrait-on utiliser un dictionnaire pour représenter des 
ensembles de mots
lorsque l'objectif est de vérifier si un mot appartient à un ensemble ?
4/11

Dans la suite, on propose une première manière d'implémenter un ensemble de 
mots nommée trie. Il s'agit d'une structure d'arbre dans laquelle chaque noeud 
contient un booléen et
a un enfant (éventuellement vide) par lettre de l'alphabet. Pour alléger les 
représentations,
on n'affichera pas les enfants vides. Un chemin de la racine vers un noeud de 
l'arbre correspond donc à une suite de lettres, c'est-à-dire un mot. On dit 
qu'un mot appartient au trie si
le dernier noeud du chemin étiqueté par ce mot depuis la racine contient true.
Par exemple, l'ensemble de mots {le, lettre, lettrine, liste} est représenté 
par le trie en figure 1. Le mot "let" n'est pas dans ce trie car le noeud sur 
lequel on arrive en lisant ce mot
depuis la racine n'est pas étiquetté par true.
false

l
false

e

e
true

i

true

false

t

s

false

false

t

t

false

false

r

e

false

true

i
false

n
false

e
true

F IGURE 1 - Un exemple de trie
Q14. Dessiner le trie correspondant à l'ensemble de mots suivants : {en, 
entier, bot, bottier,
bottine, routier, routine}.
Dans la suite du problème, le langage OCaml sera le seul langage utilisé.
Pour manipuler des mots en OCaml, on choisit d'utiliser des listes de lettres ; 
une lettre étant
représentée par un char. On commence par se doter d'une fonction permettant de 
convertir
un objet de type string en une liste de caractères. Il est rappelé qu'on peut 
accéder au
caractère d'indice i d'une chaîne s en OCaml avec la syntaxe s.[i] et qu'on 
peut connaître
la longueur de s via la fonction String.length.

5/11

Q15. Implémenter une fonction string_to_list : string -> char list qui s'évalue
en la liste des caractères de la chaîne passée en argument. Par exemple,
string_to_list "lettre" s'évaluera en ['l'; 'e'; 't';'t';'r';'e']. On pourra
s'appuyer sur une fonction auxiliaire si besoin, mais dans ce cas on prendra 
soin d'expliquer le rôle de cette fonction. La fonction aura une complexité 
linéaire en la taille
de la chaîne qu'on justifiera.
On considère le type récursif OCaml suivant pour implémenter un trie.
type trie = Node of bool * (char * trie) list

On omet les arbres vides, un noeud peut donc avoir un nombre variable 
d'enfants. Les
enfants d'un noeud sont stockés dans une liste de couples (lettre, arbre) et 
chaque noeud, y
compris les feuilles, contient un booléen indiquant l'éventuelle présence d'un 
mot.
Par exemple, le trie en figure 2 est représenté en OCaml par l'objet de type 
trie suivant :
Node (false,
[('l',
Node (false,
[('e', Node (true, [('s', Node (true, []))])); ('a', Node (true,
[]))]))])

false

l
false

e

a

true

true

s
true

F IGURE 2 - Un exemple de petit trie
Q16. Implémenter une fonction empty_trie : unit -> trie qui renvoie le trie 
vide ayant
le moins de noeuds possible.
Q17. Implémenter une fonction récursive max_list : int list -> int qui renvoie 
le plus
grand élément d'une liste supposée non vide.
Q18. Implémenter une fonction récursive list_map : ('a -> 'b) -> 'a list -> 'b
list qui prend en argument une fonction f et une liste lst et renvoie la liste 
des
images par f des éléments de lst, dans le même ordre. Il est interdit 
d'utiliser la
fonction List.map dans cette question.
Q19. Implémenter une fonction height : trie -> int qui calcule la hauteur d'un 
trie (la
définition de la hauteur d'un trie est la même que pour un arbre quelconque). On
pourra s'appuyer sur les deux fonctions précédentes.

6/11

Q20. Implémenter une fonction size : trie -> int qui calcule le nombre de 
noeuds dans
un trie (attention, il ne s'agit pas du nombre de mots dans le trie, tous les 
noeuds
comptent ici).
Considérons la fonction suivante sur les trie :
let rec f t =
match t with
|Node (true, []) -> 1
|Node (false, []) -> 0
|Node (b, (letter,child)::tail) -> (f child) + (f (Node (b, tail)))

Q21. Indiquer la grandeur que calcule cette fonction en expliquant pourquoi.
Q22. Implémenter une fonction is_in_trie : char list -> trie -> bool qui prend 
en
entrée un mot sous forme d'une liste de ses caractères et un trie et s'évalue 
en true
si le mot est présent dans la structure et false sinon.
Q23. Implémenter une fonction add_to_trie : char list -> trie -> trie qui prend 
un
mot sous forme d'une liste de ses caractères et un trie et qui s'évalue en un 
trie
contenant les mots contenus dans le trie passé en argument et le mot passé en
argument.
Q24. Si on regarde l'exemple du trie obtenu en Q14, quel problème semble se 
poser en
terme d'efficacité concernant la taille de la structure et d'une éventuelle 
redondance ?
On souhaite maintenant interpréter un trie comme un cas particulier d'automate 
de manière
à ce que les mots reconnus par cet automate soient ceux présents dans le trie.
Q25. Préciser ce que sont les différents composants de l'automate (états, états 
initiaux,
états finaux, transitions, alphabet) associé à un trie qu'on interprète comme 
un automate.
Q26. Dessiner l'automate associé au trie de Q14.
Pour tenter de résoudre le problème évoqué en Q24, on se propose de modifier 
l'automate
obtenu à partir d'un trie pour y supprimer les états redondants. On peut noter 
que cet automate est déterministe et donc que la lecture d'une lettre c depuis 
un état q amène à au
plus un état, noté (q, c) s'il existe. Si la lecture de c depuis q n'est pas 
possible, on parle de
blocage.
Soient deux états q et q de l'automate,  son alphabet et  sa fonction de 
transition. On
considère une relation binaire E sur les états. Deux états q et q sont en 
relation selon E, ce
que l'on note qEq , si :
- (q et q sont tous deux finaux) ou (q et q sont tous deux non finaux),
- c  , soit c est un blocage pour q et q , soit (q, c)E(q , c).
Q27. Donner un exemple d'un couple d'états sans transition sortante qui sont en 
relation
pour E dans l'automate de Q26. Même chose pour un couple d'états avec transition
sortante.
On admet que pour deux états qui sont en relation selon E, on reconnaît le même 
langage
en commençant une lecture depuis l'un ou l'autre de ces états.

7/11

Q28. En déduire une manière de simplifier l'automate obtenu en convertissant un 
trie pour
réduire au plus son nombre d'états tout en ne changeant pas le langage reconnu. 
En
donner les grandes lignes en expliquant la démarche et illustrer cette démarche 
sur
le trie contenant les mots {car, par, cal, pal}.

PROBLÈME 3
Logique implicationnelle

Un système logique est défini par :
- une syntaxe S , qui décrit la façon dont il faut écrire les formules du 
système,
- une sémantique M, qui explique le sens à leur donner,
- un système de déduction D, qui établit les règles syntaxiques permettant de 
faire des
preuves.
On introduit tout d'abord un premier système logique, le calcul propositionnel 
C P = (S P , MP , DP ) :
- S P est l'ensemble des formules définies inductivement à partir de ,  et des 
variables
propositionnelles à l'aide des connecteurs classiques , , ¬ et ,
- MP est la sémantique standard construite à partir des tables de vérité pour , 
, ¬ et
,
- DP est la déduction naturelle, dont les règles sont rappelées en annexe 1.

Q29. Si A et B sont deux formules de S P , montrer que les formules A  B et ¬A  
B sont
équivalentes à l'aide d'une table de vérité.

Q30. Si A et B sont deux formules de S P , les formules ¬A et A   sont-elles 
équivalentes ?

Q31. Si A et B sont deux formules de S P , établir en la détaillant la table de 
vérité de la
formule :
 = ((A  B)  A)  A
Que peut-on dire de cette formule ?

On dit qu'un système  de connecteurs est complet si et seulement si toute 
formule de S P
est équivalente à une formule de S P qui ne fait intervenir que les connecteurs 
de . Par
exemple, {¬, , , } est un système complet de connecteurs.

Q32. Montrer par induction sur les formules de S P que le système de 
connecteurs {¬, }
est complet.

On introduit dans la suite du problème un nouveau système logique, le calcul 
purement
implicationnel C I = (S I , MI , DI ) :
- Les formules de S I sont définies par induction de la façon suivante :
- les symboles ,  et les variables propositionnelles sont des formules de S I ,
- si A et B sont des formules de S I , alors A  B également.
Autrement dit, on restreint les formules de S P à celles qui font intervenir 
uniquement le
connecteur , d'où le nom du système.
- La sémantique MI est la sémantique standard.
- Le système de déduction DI est donné par les règles de déduction suivantes :
Peirce
ax
  ((A  B)  A)  A
, A  A
AB A
elim-
B

8/11

, A  B
intro-
AB

Autrement dit, on restreint les règles de la déduction naturelle à l'axiome, 
l'introduction
et l'élimination du  et on y ajoute un axiome, appelé la loi de Peirce.
Q33. Justifier que pour toute formule de S P , il existe une formule de S I qui 
lui est équivalente.
Q34. Prouver dans le système DI les séquents suivants :
1. A  (A  B)  B

2. A  B, B  C  A  C

3. (A  B)  C, A  C  C. On pourra utiliser l'instance suivante de la loi de
Peirce : ((C  B)  C)  C.

Q35. Rappeler ce que signifie, pour une règle d'un système de déduction, que 
d'être correcte. Montrer que les règles de DI sont toutes correctes.
Q36. S'il existe une preuve du séquent   F dans un système dont toutes les 
règles
sont correctes, quelle relation sémantique existe entre F et  ? Justifier 
brièvement la
réponse.
Q37. À l'aide d'un argument sémantique, expliquer pourquoi ce prétendu arbre de 
preuve
est incorrect. L'ensemble  est défini par  = {A  B, C  B} :
, A  A

On rappelle que si :

ax

ax
, A  A  B
elim-
ax
, A  B
, A  C  B
elim-
, A  C
intro-
AC

...   Fk
F
est une règle, les séquents   F1 , ...,   Fk au-dessus de la barre se nomment 
les prémisses de la règle et le séquent   F en est sa conclusion.
  F1

On dit qu'une règle est dérivable dans un système de déduction si on peut 
construire sa
conclusion avec les règles du système de déduction en supposant qu'on a déjà 
une preuve
de ses prémisses. Par exemple, la règle suivante est dérivable dans DI :
, A  B   A
cut
B

En effet, on peut la prouver en n'utilisant que les règles de DI via cet arbre :
supposé
, A  B
intro-
AB
B

supposé
A

elim-

Q38. Prouver le séquent (A  B)  A, ¬A  A dans le système DP .

Q39. En déduire que la loi de Peirce est dérivable dans le système de déduction 
DP . On
pourra s'aider de la question précédente et utiliser la règle du raisonnement 
par l'absurde.
9/11

Q40. On note D le système de déduction constitué des règles de DP auxquelles on 
a enlevé
le raisonnement par l'absurde et ajouté la loi de Peirce. Montrer 
réciproquement que la
règle du raisonnement par l'absurde est dérivable dans D. On pourra utiliser 
l'instance
suivante de la loi de Peirce : ((A  )  A)  A.
Q41. Que peut-on dire de D ? Justifier brièvement.

10/11

Annexe 1
Règles de la déduction naturelle

- Axiome :
, A  A

ax

- Affaiblissement :
A
aff
, B  A

- Introduction et élimination de l'implication :
, A  B
intro-
AB

AB A
elim-
B

- Introduction et éliminations du et :
 AB
elim-
A

A B
intro-
 AB

 AB
elim-
B

- Introductions et élimination du ou :
A
intro-
 AB

 AB

B
intro-
 AB

, A  C
C

- Introdution et élimination du non :
, A  
intro-¬
  ¬A

- Élimination du  :

- Raisonnement par l'absurde :

  A   ¬A
elim-¬

elim-
A
, ¬A  
ra
A

FIN
11/11

, B  C

elim-