A552. Des diviseurs à gogo
Q1 Démontrer que l’entier 3105+ 4105 est divisible par 7,13,31,43,49,181et379 mais ne l’est pas par 5 ou 11 ou 17 ou 19.
Q2 Démontrer que chacun des entiers : N1= 2125 + 1048576,
N2= 3125 + 3486784401, N3= 5125 + 9536743164062
a un nombre de diviseurs distincts qui est un multiple de 2016.
Solution proposée par Simon Pellicer
Q1.
Les entiers : 13,31,43,49,181,379 sont premiers entre eux. Or 7|49 donc on cherche à montrer que 13·31·43·49·181·379 = 58248851479|3105+ 4105. La dif- ficulté consiste à créer un algorithme qui gère de très grands nombres. Effective- ment en C++ par exemple on ne peut manipuler que des entiers<4294967295.
Ainsi il faut créer un algorithme qui utilise des chaînes de caractères pour gérer les grands nombres. On peut en proposer un (voir page 2). Ainsi à l’aide de cette algorithme on peut gérer sans aucune difficultés des nombres de la taille de : 3105+ 4105. On obtient alors :
[582488514793105 ] = [125236737537878753441860054533045969266612127846243
58248851479 ] = 2150029302861522837097518293765738083877 Donc 3105= 2150029302861522837097518293765738083877·58248851479+46710342160
De même : [582488514794105 ] = [1645504557321206042154969182557350504982735865633579863348609024
58248851479 ] =
28249562275308498570764912893491362241641012831094895
Donc 4105= 28249562275308498570764912893491362241641012831094895·58248851479+
11538509319
Or 11538509319+46710342160 = 58248851479⇔11538509319+46710342160≡ 0 (mod 58248851479)
Cela conclut.
Les entiers 5,11,17,19 sont premiers entre eux. Donc on cherche à montrer que 5·11·17·19 = 17765 ne divise pas 3105+ 4105. On trouve de manière similaire que 3105≡2938 (mod 17765) et 4105≡8504 (mod 17765)
Donc 3105+ 4105≡11442 (mod 17765). Ce qui conclut.
Q2.
A partir du moment on l’on sait gérer de très grands nombres il est facile de trouver la décomposition en facteurs premiers de grands nombres. Effectivement on a de nombreux algorithmes efficaces pour ce faire à notre disposition comme l’algorithme du crible quadratique, l’algorithme rho de Poullard, l’algorithme de division classique...
Ainsi sans trop de difficultés on trouve :
N1= 220·32·11·43·211·281·331·5419·86171·664441·1564921
soitd(N1) = (20 + 1)·(2 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1) = 32256
N2= 22·320·72·31·43·61·211·271·547·1051·2269·24151·3369031·3454081· 374857981681
soitd(N2) = (2 + 1)·(20 + 1)·(2 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1) = 774144 N3= 2·32·520·72·29·43·61·127·421·449·521·7603·7621·5236141·15216601· 4698932281·1354224218968567573270561
soitd(N3) = (1 + 1)·(2 + 1)·(20 + 1)·(2 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1)·(1 + 1) = 3096576
On a bien la condition énoncée car 2016|d(N1), 2016|d(N2), 2016|d(N3).
Voici l’algorithme utilisée pour gérer les très grands nombres :
1 #include<iostream>
2 #include<string>
3 #include<iterator>
4 #include<iterator>
5 #include<vector>
6 #include<sstream>
7 #include<algorithm>
8 #include<math.h>
9 using namespace std;
10
11 std::string to_string(long long int i)
12 {
13 std::stringstream ss;
14 ss << i;
15 return ss.str();
16 }
17 void blank(string &nombre1, string &nombre2)
18 {
19 bool isItTrue(true);
20 if(nombre1.size() > nombre2.size())
21 {
22 isItTrue = true;
23 }
24 if(nombre2.size() > nombre1.size())
25 {
26 isItTrue = false;
27 }
28 string zero("");
29 if(isItTrue)
30 {
31 for(int j = 0;j<nombre1.size() - nombre2.size();++j)
32 {
33 zero+="0";
34 }
35 nombre2 = zero + nombre2;
36 }
37 else{
38 for(int j = 0;j<nombre2.size()-nombre1.size();++j)
39 {
40 zero+="0";
41 }
42 nombre1 = zero + nombre1;
43 }
44 }
45 string sum(string nombre1, string nombre2)
46 {
47 string result("");
48 unsigned int retenue(0);
49 unsigned int somme(0);
50 unsigned int unite(0);
51 blank(nombre1,nombre2);
52 for(unsigned int i = 0;i < nombre2.size();++i)
53 {
54 somme = (nombre1[nombre1.size()-1-i]-’0’)+(nombre2[nombre2.size() -1-i]-’0’) + retenue;
55 unite = somme%10;
56 retenue = (somme - unite)/10;
57 result += to_string(unite);
58 }
59 if(retenue !=0)
60 {
61 result+=to_string(retenue);
62 }
63 reverse(begin(result), end(result));
64 return result;
65 }
66 string multiply(string nombre1, string nombre2)
67 {
68 vector<string>allSum;
69 string result("");
70 unsigned int retenue1(0);
71 unsigned int somme1(0);
72 unsigned int unite1(0);
73 int k = 1;
74 blank(nombre1, nombre2);
75 for(unsigned int t = 0;t<nombre2.size();++t){
76 for(unsigned int i = 0;i < nombre2.size();++i)
77 {
78 somme1 = (nombre1[nombre1.size()-1-t]-’0’)*(nombre2[nombre2.size ()-1-i]-’0’) + retenue1;
79 unite1 = somme1%10;
80 retenue1 = (somme1 - unite1)/10;
81 result += to_string(unite1);
82 }
83 if(retenue1 !=0)
84 {
85 result+=to_string(retenue1);
86 }
87 retenue1 = 0;
88 reverse(begin(result), end(result));
89 allSum.push_back(result);
90 result = "";
91 for(int y = 0;y<k;++y)
92 {
93 result +="0";
94 }
95 k++;
96 }
97 result = "";
98 result = allSum.at(0);
99
100 for(int m = 1;m<allSum.size();++m)
101 {
102 result = sum(result, allSum.at(m));
103 }
104 return result;
105 106 }
107 void deleteBlancks(string &result)
108 {
109 bool interrogation(false);
110 int k(0);
111 if(result[0] == ’0’)
112 {
113 interrogation = true;
114 }
115 while(interrogation == true)
116 {
117 for(int i = 0;i<result.size();++i)
118 {
119 if(result[i] == ’0’)
120 {
121 k++;
122 }
123 else{interrogation = false; i = result.size();}
124 }
125 interrogation = false;
126 }
127 result.erase(0,k);
128 }
129 bool chercherOccurence(string result, int a)
130 {
131 vector<int>lastDigits;
132 int n(0);
133 for(int i = 0;i<a;++i)
134 {
135 lastDigits.push_back(result[result.size()-i]-’0’);
136 }
137 for(int y = 0;y<10;++y)
138 {
139 if(find(lastDigits.begin(), lastDigits.end(), y) !=lastDigits.end ())
140 {
141 n++;
142 }
143 }
144 if(n > 2 || n<2 || find(lastDigits.begin(), lastDigits.end(), 0)!=
lastDigits.end())
145 {
146 return false;
147 }
148 if(n == 2)
149 {
150 return true;
151 }
152 }
153 bool chercherOccurence2(string result, int a)
154 {
155 vector<int>lastDigits;
156 int n(0);
157 for(int i = 0;i<result.size();++i)
158 {
159 lastDigits.push_back(result[i]-’0’);
160 }
161 for(int y = 0;y<10;++y)
162 {
163 if(find(lastDigits.begin(), lastDigits.end(), y) !=lastDigits.end ())
164 {
165 n++;
166 }
167 }
168 if(n > a || n<a)
169 {
170 return false;
171 }
172 if(n == a)
173 {
174 return true;
175 }
176 }
177 int main()
178 {
179 string nombre1("");
180 string result("");
181 unsigned int l(0);
182 cin>>l;
183 cin>>nombre1;
184 result = nombre1;
185 for(unsigned long int i = 1;i<l;++i)
186 {
187 cout<<i<<endl;
188 result = multiply(result,nombre1);
189 deleteBlancks(result);
190 }
191 cout<<result<<endl;
192 return 0;
193 }