C 468
#include <stdlib.h>
#include <stdio.h>
#define a(s)fputs(s,stdout);
#define b(c)putchar(c);
int r;int z(char*s,int m){for(int i=0;i++<=m;)a(s)b(47)b(r+48)b(61)char*t=s;
while(*++t==48);a(t)while(m--)a(s)b(*s)b(10)}char x[10][60];
int main(int c,char**v){r=atoi(v[1]);int n=atoi(v[2]),q=10*r-1,d=0,p;
while(d++<9){p=r*d;char*y=x[d];do{p*=10;*y++=p/q+48;p%=q;}while(p!=r*d);}
d=1;p=q=0;while(n--){r==5&p<6?z(x[7],7*q+p++):(z(x[d],(r==5&d==7)?7*q+6:q),
++d>9?q+=d=1,p=0:0);}}
(มีการเพิ่มบรรทัดใหม่ที่ไม่นับในจำนวนไบต์ด้านบนเพื่อกำจัดแถบเลื่อนใช่การขึ้นบรรทัดใหม่สุดท้ายจะถูกนับ)
คาดหวังข้อโต้แย้งในบรรทัดคำสั่งและถือว่าเอาต์พุตมาตรฐานยอมรับ ASCII รันไทม์คือ O (จำนวนไบต์เอาท์พุท) = O (n * n)
printf
ไม่ฉันไม่สามารถใช้ ใช้เวลามากเกินไปและผลักโปรแกรมเกินขีด จำกัด นาทีบนเดสก์ท็อปของฉัน เนื่องจากเป็นกรณีทดสอบบางกรณีใช้เวลาประมาณ 30 วินาที
อัลกอริทึมปฏิบัติกับผลลัพธ์เป็นสตริงไม่ใช่ตัวเลขเนื่องจากมีจำนวนมหาศาลอย่างรวดเร็วและมีรูปแบบที่แข็งแกร่งในเอาต์พุต
ค่อนข้างอวดดี:
#include <stdlib.h>
#include <stdio.h>
/* r is as in the problem description */
int r;
void show_line(const char* num, int repeats) {
for (int i=0; i <= repeats; ++i)
fputs(num, stdout);
printf("/%c=", '0'+r);
/* Assume the repeated num is a solution. Just move the first
digit and skip any resulting leading zeros. */
const char* num_tail = num;
++num_tail;
while (*num_tail=='0')
++num_tail;
fputs(num_tail, stdout);
while (repeats--)
fputs(num, stdout);
printf("%c\n", *num);
}
/* sol[0] is unused. Otherwise, sol[d] is the repeating digits in the
decimal representation of (r*d)/(10*r-1). */
char sol[10][60];
int main(int argc, char** argv) {
r = atoi(argv[1]);
int n = atoi(argv[2]);
int q = 10*r-1;
int d = 0;
/* Populate the strings in sol[]. */
while (d++<9) {
int p = r*d;
char* sol_str = sol[d];
/* Do the long division p/q in decimal, stopping when the remainder
is the original dividend. The integer part is always zero. */
do {
p *= 10;
*sol_str++ = p/q + '0';
p %= q;
} while (p != r*d);
}
/* Output the answers. */
d = 1;
int repeats = 0;
int r5x7_repeats = 0;
while (n--) {
if (r==5 && r5x7_repeats<6) {
show_line(x[7], 7*repeats + r5x7_repeats);
} else {
if (r==5 && d==7)
show_line(x[d], 7*repeats + 6);
else
show_line(x[d], repeats);
if (++d > 9) {
d = 1;
++repeats;
r5x7_repeats = 0;
}
}
}
}
พิสูจน์
ว่าโปรแกรมแก้ปัญหา:
(ในหลักฐานที่ใช้ประกอบการทั้งหมดและฟังก์ชั่นที่จะเป็นฟังก์ชั่นทางคณิตศาสตร์ที่จริงไม่ได้การดำเนินงานคอมพิวเตอร์ที่ใกล้เคียงกับพวกเขา. ^
หมายถึงการยกกำลังไม่ xor บิต.)
เพื่อความชัดเจนฉันจะใช้ฟังก์ชันToDec
เพื่ออธิบายกระบวนการทั่วไปของการเขียนตัวเลขเป็นลำดับเลขทศนิยม ช่วงคือชุดของ tuples {0...9}
สั่งซื้อบน ตัวอย่างเช่น,
ToDec(2014) = (2, 0, 1, 4).
สำหรับจำนวนเต็มบวกn
กำหนดL(n)
ให้เป็นจำนวนหลักในการแทนทศนิยมของn
; หรือ,
L(n) = 1+floor(log10(n)).
สำหรับจำนวนเต็มบวกk
และจำนวนเต็มไม่เป็นลบn
ด้วยL(n)<k
ให้นิยามRep_k(n)
เป็นจำนวนจริงที่ได้รับโดยการเพิ่มศูนย์หน้าตัวเลขทศนิยมn
ถ้าจำเป็นเพื่อให้ได้k
ผลรวมตัวเลขแล้วซ้ำk
ตัวเลขเหล่านั้นซ้ำหลังจุดทศนิยม เช่น
Rep_4(2014) = .201420142014...
Rep_5(2014) = .020140201402...
การคูณRep_k(n) * 10^k
จะให้ตัวเลขn
ก่อนจุดทศนิยมและตัวเลข (ศูนย์เป็นศูนย์) ของการn
ทำซ้ำอย่างไม่สิ้นสุดหลังจุดทศนิยม ดังนั้น
Rep_k(n) * 10^k = n + Rep_k(n)
Rep_k(n) = n / (10^k - 1)
รับจำนวนเต็มบวกr
สมมติว่าx
เป็นวิธีแก้ปัญหาและ
ToDec(x) = ( x_1, x_2, ..., x_k )
ที่และx_1 != 0
k = L(x)
จะเป็นวิธีการแก้ไขx
เป็นหลายตัวr
และ
ToDec(x/r) : ( x_2, x_3, ..., x_k, x_1 ).
การใช้Rep_k
ฟังก์ชันให้สมการที่ดี:
10*Rep_k(x) = x_1 + Rep_k(x/r)
ใช้แบบฟอร์มที่ปิดจากด้านบน
10x / (10^k - 1) = x_1 + x / r / (10^k - 1)
x = x_1 * r * (10^k-1) / (10r - 1)
x_1
{1 ... 9}
จะต้องอยู่ในชุด ถูกระบุว่าจะอยู่ในชุดr
{2 ... 9}
ตอนนี้คำถามเดียวก็คือว่าk
สูตรข้างต้นx
มีค่าเป็นจำนวนเต็มบวกเท่าใด เราจะพิจารณาแต่ละค่าที่เป็นไปได้ของr
แต่ละรายการ
เมื่อr
= 2, 3, 6, 8, หรือ 9, 10r-1
คือ 19, 29, 59, 79, หรือ 89 ตามลำดับ ในทุกกรณีส่วนที่p = 10r-1
เป็นนายก ในตัวเศษ10^k-1
สามารถมีได้หลายตัวp
เท่านั้นซึ่งจะเกิดขึ้นเมื่อ
10^k = 1 (mod p)
ชุดของการแก้ปัญหาถูกปิดภายใต้การบวกและภายใต้การลบที่ไม่ส่งผลให้จำนวนลบ k
ดังนั้นชุดประกอบด้วยหลายทั้งหมดของบางปัจจัยร่วมกันซึ่งยังเป็นวิธีการแก้ปัญหาในเชิงบวกอย่างน้อยสำหรับ
เมื่อไหร่r = 4
และ10r-1 = 39
; หรือเมื่อr = 7
และ10r-1 = 69
หารคือ 3 p=(10r-1)/3
ครั้งสำคัญที่แตกต่างกัน 10^k-1
เป็นผลคูณของ 3 เสมอและไม่มีปัจจัยอื่นใดในตัวเศษที่สามารถคูณได้p
อีกครั้งดังนั้นปัญหาจึงลดลง
10^k = 1 (mod p)
k
และอีกครั้งการแก้ปัญหาที่มีทั้งหมดหลายของการแก้ปัญหาในเชิงบวกน้อยสำหรับ
[ยังไม่เสร็จ...]
gprof
กรณีการป้อนข้อมูลหนึ่งรายการสำหรับโปรแกรมของฉันใช้เวลาน้อยกว่าครึ่งวินาทีในรหัสของฉัน แต่ใช้เวลาทั้งหมดประมาณ 80 วินาทีซึ่งฉันคิดว่าต้องปิดกั้นเอาต์พุตเป็นส่วนใหญ่