【题目链接】

ybt 1933:【05NOIP普及组】循环
洛谷 P1050 [NOIP2005 普及组] 循环

【题目考点】

1.高精度

2.数学

【解题思路】

要求最后k位的循环长度,可以从低位向高位看。
假设n的最后k位为dkdk−1...d2d1d_kd_{k-1}...d_2d_1dk​dk−1​...d2​d1​

  • 先看最低位d1d_1d1​,假设d1l1d_1^{l_1}d1l1​​的最后一位位是d1d_1d1​,它的循环长度为l1l_1l1​
  • 然后看倒数两位d2d1d_2d_1d2​d1​,以(d2d1)l1(d_2d_1)^{l_1}(d2​d1​)l1​为单位进行累乘,可以保证结果的个位是d1d_1d1​,假设累乘l2l_2l2​次,(d2d1)l1l2(d_2d_1)^{l_1l_2}(d2​d1​)l1​l2​的倒数第2位是d2d_2d2​,即末两位是d2d1d_2d_1d2​d1​,循环长度为l1l2l_1l_2l1​l2​
  • 然后看倒数3位d3d2d1d_3d_2d_1d3​d2​d1​,以(d3d2d1)l1l2(d_3d_2d_1)^{l_1l_2}(d3​d2​d1​)l1​l2​为单位进行累乘,可以保证末两位是d2d1d_2d_1d2​d1​,假设累乘l3l_3l3​次后(d3d2d1)l1l2l3(d_3d_2d_1)^{l_1l_2l_3}(d3​d2​d1​)l1​l2​l3​的倒数第3位是d3d_3d3​,即末3位是d3d2d1d_3d_2d_1d3​d2​d1​,那么循环长度为l1l2l3l_1l_2l_3l1​l2​l3​
    以此类推,直到求出倒数k位的循环长度
  • 如果累乘10次后,结果的末几位与原数字仍然不同,那么就不会发生循环,输出-1。

说明:
假设现在在看倒数m位,dm...d2d1d_m...d_2d_1dm​...d2​d1​,以(dm...d2d1)l1l2...lm−1(d_m...d_2d_1)^{l_1l_2...l_{m-1}}(dm​...d2​d1​)l1​l2​...lm−1​为单位进行累乘,可以保证最后m-1位为dm−1...d2d1d_{m-1}...d_2d_1dm−1​...d2​d1​。变化的只有结果的倒数第m位,该位置可能的数字只有0~9这10种。

  • 如果每次乘(dm...d2d1)l1l2...lm−1(d_m...d_2d_1)^{l_1l_2...l_{m-1}}(dm​...d2​d1​)l1​l2​...lm−1​得到的倒数第m位都不同,那么10次累乘中,一定至少有一次其倒数第m位的值与dmd_mdm​相同。
  • 如果10次累乘中,倒数第m位都没能等于dmd_mdm​,说明这10次中,倒数第m位出现了重复的数字,倒数第m位数字的变化存在循环,而这个循环中没有dmd_mdm​这个数字。所以dm...d2d1d_m...d_2d_1dm​...d2​d1​不会循环出现,应该输出-1。

解法1:

严格按照上述方法执行,每次循环只看末m位,前先求累乘单位(dm...d2d1)l1l2...lm−1(d_m...d_2d_1)^{l_1l_2...l_{m-1}}(dm​...d2​d1​)l1​l2​...lm−1​,需要用到快速幂。

解法2:

整体思路与上述方法大体相同,不过直接取n的末k位作为累乘单位,不再分别取末1位,末2位。。。

  • 先看最低位d1d_1d1​,假设(dkdk−1...d2d1)l1(d_kd_{k-1}...d_2d_1)^{l_1}(dk​dk−1​...d2​d1​)l1​的最后一位位是d1d_1d1​,它的循环长度为l1l_1l1​
  • 然后看倒数两位d2d1d_2d_1d2​d1​,以(dkdk−1...d2d1)l1(d_kd_{k-1}...d_2d_1)^{l_1}(dk​dk−1​...d2​d1​)l1​为单位进行累乘,可以保证结果的个位是d1d_1d1​,假设累乘l2l_2l2​次,(dkdk−1...d2d1)l1l2(d_kd_{k-1}...d_2d_1)^{l_1l_2}(dk​dk−1​...d2​d1​)l1​l2​的倒数第2位是d2d_2d2​,即末两位是d2d1d_2d_1d2​d1​,循环长度为l1l2l_1l_2l1​l2​
  • 然后看倒数3位d3d2d1d_3d_2d_1d3​d2​d1​,以(dkdk−1...d2d1)l1l2(d_kd_{k-1}...d_2d_1)^{l_1l_2}(dk​dk−1​...d2​d1​)l1​l2​为单位进行累乘,可以保证末两位是d2d1d_2d_1d2​d1​,假设累乘l3l_3l3​次后(dkdk−1...d2d1)l1l2l3(d_kd_{k-1}...d_2d_1)^{l_1l_2l_3}(dk​dk−1​...d2​d1​)l1​l2​l3​的倒数第3位是d3d_3d3​,即末3位是d3d2d1d_3d_2d_1d3​d2​d1​,那么循环长度为l1l2l3l_1l_2l_3l1​l2​l3​
  • 如此来做,上一次循环的累乘的结果可以直接作为下一次循环的累乘单位,可以省去解法1中做快速幂的过程。

【题解代码】

代码中几个Multiply函数名字相同,参数个数或类型不同,构成函数重载,几个函数都可以被正确使用。

解法1:

#include<bits/stdc++.h>
using namespace std;
#define N 305
void numcpy(int a[], int b[])//b拷贝给a
{for(int i = 0; i <= b[0]; ++i)//把r赋值给a a[i] = b[i];
}
void Multiply(int a[], int b[], int m)//a *= b 高精乘高精 结果只取末m位
{int r[N] = {}, ri;for(int i = 1; i <= a[0]; ++i){int c = 0;for(int j = 1; j <= b[0]; ++j){r[i+j-1] += a[i]*b[j] + c;c = r[i+j-1] / 10;r[i+j-1] %= 10; }r[i+b[0]] += c;}ri = a[0] + b[0];while(r[ri] == 0 && ri > 1)ri--;r[0] = ri;if(r[0] > m)r[0] = m; numcpy(a, r);
}
void Multiply(int a[], int b)//a *= b 高精乘低精
{int c = 0, i;for(i = 1; i <= a[0]; ++i){a[i] = a[i]*b + c;c = a[i] / 10;a[i] %= 10; }while(c > 0){a[i] = c % 10;c /= 10;i++;}while(a[i] == 0 && i > 1)i--;a[0] = i;
}
void Divide(int a[], int b) //高精除低精 a/=b
{int x = 0, ai;//余数 for(int i = a[0]; i >= 1; i--){x = x * 10 + a[i];a[i] = x / b;x %= b;}ai = a[0];while(a[ai] == 0 && ai > 1)ai--;a[0] = ai;
}
void fastPower(int a[], int b[], int m)//快速幂 a^b取末m位 ,结果保存给a
{int r[N] = {1, 1}, c[N];//a为基数,c为指数,r为结果 numcpy(c, b);while(!(c[0] == 1 && c[1] == 0))//c != 0{if(c[1] % 2 == 1)//用b的个位判断其是否是偶数 Multiply(r, a, m); Multiply(a, a, m);Divide(c, 2);}numcpy(a, r);
}
void tonum(int a[], char s[])//字符串转为数字数组
{int len = strlen(s);for(int i = 1; i <= len; ++i)a[i] = s[len-i] - '0';a[0] = len;
}
void cutNum(int a[], int n, int b[])//截取数字a的后n位 赋值给数字b
{for(int i = 1; i <= n; ++i)b[i] = a[i];b[0] = n;
}
int main()
{int n[N] = {}, a[N] = {}, b[N] = {}, l[N] = {1,1}, k;//a:累乘单位 l:循环长度 初值为1 char s[N];cin >> s >> k;tonum(n, s);for(int i = 1; i <= k; ++i)//i:看后i位 {cutNum(n, i, a);//构造a为n的后i位 fastPower(a, l, i);//n的后i位累乘l次,使a成为累乘单位 cutNum(n, i, b);//构造b为n的后i位 bool isFound = false; //第i位的循环长度是否找到 for(int j = 1; j <= 10; ++j){Multiply(b, a, i);if(b[i] == n[i])//如果倒数第i位又变回为原来的倒数第i位 {Multiply(l, j);//找到第i位的循环长度为j isFound = true;break;}}if(isFound == false){//如果没找到,则不存在循环长度 cout << -1;return 0;}}for(int i = l[0]; i >= 1; i--)//输出循环长度cout << l[i]; return 0;
}

解法2:

#include<bits/stdc++.h>
using namespace std;
#define N 305
int k;//结果取末k位
void numcpy(int a[], int b[])//b拷贝给a
{for(int i = 0; i <= b[0]; ++i)//把r赋值给a a[i] = b[i];
}
void Multiply(int a[], int b[], int r[])//a * b = r 高精乘高精 结果只取末k位
{for(int i = 1; i <= a[0]; ++i){int c = 0;for(int j = 1; j <= b[0]; ++j){r[i+j-1] += a[i]*b[j] + c;c = r[i+j-1] / 10;r[i+j-1] %= 10; }r[i+b[0]] += c;}int ri = a[0] + b[0];while(r[ri] == 0 && ri > 1)ri--;r[0] = ri;if(r[0] > k)r[0] = k;
}
void Multiply(int a[], int b[])//a *= b 高精乘高精 结果只取末k位
{int r[N] = {};Multiply(a, b, r);numcpy(a, r);
}
void Multiply(int a[], int b)//a *= b 高精乘低精
{int c = 0, i;for(i = 1; i <= a[0]; ++i){a[i] = a[i]*b + c;c = a[i] / 10;a[i] %= 10; }while(c > 0){a[i] = c % 10;c /= 10;i++;}while(a[i] == 0 && i > 1)i--;a[0] = i;
}
void tonum(int a[], char s[])//字符串转为数字数组
{int len = strlen(s);for(int i = 1; i <= len; ++i)a[i] = s[len-i] - '0';a[0] = len;
}
int main()
{int n[N] = {}, a[N] = {}, b[N] = {}, c[N] = {}, l[N] = {1,1};//a:累乘单位 l:循环长度 初值为1 char s[N];cin >> s >> k;tonum(n, s);numcpy(a, n);//累乘单位a初值为nfor(int i = 1; i <= k; ++i)//i:看后i位 {bool isFound = false; //第i位的循环长度是否找到 c[0] = c[1] = 1;//c = 1; 累乘乘积 for(int j = 1; j <= 10; ++j){Multiply(c, a);//高精乘高精 c *= a;memset(b, 0, sizeof(b));Multiply(c, n, b);//高精乘高精 b = a*nif(b[i] == n[i])//如果倒数第i位又变回为原来的倒数第i位 {Multiply(l, j);//高精乘低精 找到第i位的循环长度为j isFound = true;break;}}if(isFound == false){//如果没找到,则不存在循环长度 cout << -1;return 0;}numcpy(a, c);//使当前c的值为下一次的累乘单位a了}for(int i = l[0]; i >= 1; i--)//输出循环长度cout << l[i]; return 0;
}

信息学奥赛一本通 ybt 1933:【05NOIP普及组】循环 | 洛谷 P1050 [NOIP2005 普及组] 循环相关推荐

  1. 信息学奥赛一本通 1392:繁忙的都市(city) | 洛谷 P2330 [SCOI2005]繁忙的都市

    [题目链接] ybt 1392:繁忙的都市(city) 洛谷 P2330 [SCOI2005]繁忙的都市 [题目考点] 1. 图论 最小生成树 [解题思路] 将题目叙述转为图论概念,交叉路口为顶点,道 ...

  2. 信息学奥赛一本通 1375:骑马修栅栏(fence) | 洛谷 P2731 [USACO3.3]骑马修栅栏 Riding the Fences

    [题目链接] ybt 1375:骑马修栅栏(fence) 洛谷 P2731 [USACO3.3]骑马修栅栏 Riding the Fences [题目考点] 1. 图论:欧拉回路 欧拉回路存在的条件: ...

  3. 信息学奥赛一本通 1107:校门外的树 | 1931:【05NOIP普及组】校门外的树 | OpenJudge NOI 1.6 06 | 洛谷 P1047 [NOIP2005 普及组] 校门外的树

    [题目链接] ybt 1107:校门外的树 ybt 1931:[05NOIP普及组]校门外的树 OpenJudge NOI 1.6 06:校门外的树 洛谷 P1047 [NOIP2005 普及组] 校 ...

  4. 信息学奥赛一本通 1103:陶陶摘苹果 |1930:【05NOIP普及组】陶陶摘苹果 | OpenJudge NOI 1.6 02 | 洛谷 P1046 [NOIP2005 普及组] 陶陶摘苹果

    [题目链接] ybt 1103:陶陶摘苹果 ybt 1930:[05NOIP普及组]陶陶摘苹果 OpenJudge NOI 1.6 02:陶陶摘苹果 洛谷 P1046 [NOIP2005 普及组] 陶 ...

  5. 信息学奥赛一本通 1839:【05NOIP提高组】谁拿了最多奖学金 | OpenJudge NOI 1.9 04:谁拿了最多奖学金 | 洛谷 P1051 [NOIP2005 提高组] 谁拿了最多奖学金

    [题目链接] ybt 1839:[05NOIP提高组]谁拿了最多奖学金 OpenJudge NOI 1.9 04:谁拿了最多奖学金 洛谷 P1051 [NOIP2005 提高组] 谁拿了最多奖学金 [ ...

  6. 信息学奥赛一本通 1111:不高兴的津津 | 1926:【04NOIP普及组】不高兴的津津| OpenJudge NOI 1.9 03 | 洛谷 P1085 [NOIP2004 普及组] 不高兴的津津

    [题目链接] ybt 1111:不高兴的津津 ybt 1926:[04NOIP普及组]不高兴的津津 OpenJudge NOI 1.9 03:不高兴的津津 洛谷 P1085 [NOIP2004 普及组 ...

  7. 信息学奥赛一本通 1074:津津的储蓄计划 | 1835:【04NOIP提高组】津津的储蓄计划 | OpenJudge NOI 1.5 22

    [题目链接] ybt 1074:津津的储蓄计划 ybt 1835:[04NOIP提高组]津津的储蓄计划 OpenJudge NOI 1.5 22:津津的储蓄计划 [题目考点] 1. 循环.判断 [解题 ...

  8. 洛谷——P1046 [NOIP2005 普及组] 陶陶摘苹果

    P1046 [NOIP2005 普及组] 陶陶摘苹果 题目描述 陶陶家的院子里有一棵苹果树,每到秋天树上就会结出 1010 个苹果.苹果成熟的时候,陶陶就会跑去摘苹果.陶陶有个 3030 厘米高的板凳 ...

  9. 洛谷P1047 [NOIP2005 普及组] 校门外的树

    题目描述 某校大门外长度为 ll 的马路上有一排树,每两棵相邻的树之间的间隔都是 11 米.我们可以把马路看成一个数轴,马路的一端在数轴 00 的位置,另一端在 ll 的位置:数轴上的每个整数点,即  ...

最新文章

  1. 冷热分离和直接使用大数据库_中台有“数”:大数据技术为苏宁818保驾护航
  2. java.lang.IllegalArgumentException: Path index does not start with a / character
  3. 弗吉尼亚理工计算机科学排名,2020年弗吉尼亚理工大学排名TFE Times美国最佳计算机科学硕士专业排名第45...
  4. P5025-[SNOI2017]炸弹【tarjan,线段树优化建图】
  5. 隐藏鼠标指针_Mac鼠标光标消失怎么办?苹果电脑鼠标指针不显示的解决方法
  6. pandas保存为csv格式文件
  7. 项目实战-使用PySpark处理文本多分类问题
  8. USACO 4.3.1 Buy Low, Buy Lower
  9. 计算机网络谢希仁课后答案第七版答案完整版
  10. 谁说Mac系统下不能搞科研?MacOS科研软件汇总
  11. 【笔记】Opencv 绘制朱利亚(Julia)集合图形
  12. SAP 系统银行账户管理
  13. EXCEL 删除重复项并保留最大最小值
  14. 经典语录(确实经典)
  15. 【有利可图网】PS实战系列:简单易学的PS把照片转素描效果
  16. 极豆科技加入飞桨技术伙伴计划,共筑智能网联汽车新生态
  17. buct oj 最大公共子序列问题
  18. 在中断函数和MAIN函数中同时调用同一个函数的有趣现象
  19. 迷你英雄无限服务器没了吗,迷你英雄:无限无法连接服务器是什么原因
  20. 程序员的创世传说 第六节 棚户区的怪人

热门文章

  1. Javascript 链式运动框架——逐行分析代码,让你轻松了解运动的原理
  2. 用if语句表达区间分支
  3. 用Python实现磁盘IO操作全攻略,让数据流动起来!
  4. 写了4年博客,我终于也出了一本书。
  5. fail-fast机制(遍历的同时删除List中的对象)
  6. 前端18个月难度翻番?来这里把握大前端技术本质进展丨稀土开发者大会
  7. 最新、最前沿AI论文哪里找?
  8. jeecg之弹窗插件lhgdialog小结
  9. maven--私服的搭建(Nexus的使用)
  10. Eclipse设置:背景与字体大小和xml文件中字体大小调整