当前位置: 首页 > news >正文

练习-纪律问题(幂运算)

问题描述

一年级一班有 n 个小朋友坐成一排,统计了这些小朋友的爱好后,老师得知了他们一共有 m 种爱好,每个小朋友会拥有这些爱好中的一种。

如果相邻的小朋友爱好相同,那么他们上课时就会忍不住悄悄说话,违反课堂纪律。

老师想知道,一种有多少种状态可能发生违法记录的现象。

答案对 100003取模。

输入格式

输入包括两个整数 m,n含义见上文。

输出格式

输出一个整数,代表模 100003 的意义下共有多少种可能的答案。

样例输入

2 3

样例输出

6

分析问题:

总排列数
  • 每个小朋友有 m 种选择,n 个小朋友的总排列数为:

不发生违法记录的排列数
  • 如果没有任何相邻小朋友的爱好相同,那么:

    • 第一个小朋友有 m 种选择。

    • 第二个小朋友不能和第一个相同,有 m-1 种选择。

    • 第三个小朋友不能和第二个相同,有 m-1 种选择。

    • 以此类推,后面的每个小朋友都有 m-1 种选择。

  • 因此,不发生违法记录的排列数为:

发生违法记录的排列数
  • 发生违法记录的状态数 = 总排列数 - 不发生违法记录的排列数。

解题代码:

#include <bits/stdc++.h>  
using namespace std;       
typedef long long ll;     
const int p = 100003;    

// 定义快速幂函数qmi(a, n),用于计算a的n次方模p
ll qmi(ll a, ll n) {
  ll res = 1;              // 初始化结果为1
  while (n > 0) {          // 当n大于0时循环
    if (n & 1) {           // 如果n的最低位是1
      res = (res * a) % p; // 将res乘以a并取模p
    }
    a = (a * a) % p;       // 将a自乘并取模p
    n >>= 1;               // 将n右移一位,相当于n除以2
  }
  return res;              // 返回计算结果
}

int main() {
  ll m, n;                 
  cin >> m >> n;           

  // 计算所有可能的排列数zong,即m的n次方模p
  ll zong = qmi(m, n) % p;

  // 计算不发生违法记录的排列数buweifa,即m乘以(m-1)的(n-1)次方模p
  // 第一个小朋友有m种选择,后面的每个小朋友有(m-1)种选择(不能和前一个小朋友的爱好相同)
  ll buweifa = m * qmi(m - 1, n - 1) % p;

  // 计算发生违法记录的排列数ans,即总排列数减去不发生违法记录的排列数
  ll ans = zong - buweifa;

  // 如果ans为负数,则加上p以保证结果为正数
  if (ans < 0) {
    ans += p;
  }

  // 输出最终结果,即ans模p
  cout << ans % p;

  return 0;                // 程序正常结束
}

代码说明:

1. 为什么 ll zong = qmi(m, n) % p 和 ll buweifa = m * qmi(m - 1, n - 1) % p 要模上 p

原因
  • qmi 函数内部已经取模:确实,qmi 函数在计算过程中会对每一步的结果取模 p,因此 qmi(m, n) 的结果已经是 m^n % p

  • 额外的取模是为了防止溢出

    • 在计算 buweifa = m * qmi(m - 1, n - 1) 时,qmi(m - 1, n - 1) 的结果可能已经接近 p(最大为 p-1)。

    • 如果 m 也很大,那么 m * qmi(m - 1, n - 1) 的结果可能会超过 long long 的范围,导致溢出。

    • 因此,在乘法操作后再次取模 p,可以确保结果不会溢出,同时保持结果的正确性。

总结
  • qmi 函数内部的取模是为了保证幂运算的结果不溢出。

  • 外部的取模是为了防止乘法操作后的结果溢出。


2. 为什么最后判断大小后不能直接输出 ans,而是输出 ans % p

原因
  • ans 的计算可能为负数

    • ans = zong - buweifa,如果 zong < buweifa,那么 ans 会是负数。

    • 在模运算中,负数的结果需要调整为正数,因此代码中通过 if (ans < 0) ans += p; 来保证 ans 是非负数。

  • 输出 ans % p 是为了确保结果在模数范围内

    • 即使 ans 已经是非负数,它仍然可能大于 p(例如,如果 zong 和 buweifa 都接近 pans 可能接近 2p)。

    • 输出 ans % p 可以确保结果始终在 [0, p-1] 的范围内,符合题目的要求。

总结
  • 判断大小后调整 ans 是为了处理负数情况。

  • 输出 ans % p 是为了确保结果在模数范围内,避免结果超出 [0, p-1]

相关文章:

  • react__jsx语法
  • Angular由一个bug说起之十四:SCSS @import 警告与解决⽅案
  • 【Godot4.0】EasyClock时钟组件
  • 自动同步多服务器下SQL脚本2.0
  • Python:函数式编程
  • 达梦数据库中插入导出图片的方法与应用
  • uniapp+微信小程序+最简单局部下拉刷新实现
  • 看不见的“健康杀手”来袭,微塑料竟威胁人体与植物光合作用
  • 多肽纯度如何选择?
  • 【2步解决】phpstudy开机自启(自动启动phpstudy、mysql、nignx或apache、自动打开网址)
  • 自学Java-Java高级技术(单元测试、反射、注解、动态代理)
  • 深度迁移学习实战指南:从理论到产业级应用
  • Windows Wise Care 365 PRO-中文便携版
  • 【C++入门】变量和基本类型
  • Win10 下搭建免费的 FTP 服务器 FileZilla
  • 如何简单获取三个月免费试用的SSL证书
  • 处理Java中的异常
  • STC 51单片机64——关于STC8H的ADC回程误差问题
  • starrocks批量启停脚本
  • Git使用(二)--如何配置 GitHub 远程仓库及本地 Git 环境
  • 翻越高山,成为高山!浙江广厦成CBA历史第八支夺冠球队
  • 上海发布台风红色预警?实为演练,今日下午局部中雨下班请注意
  • 年内首次存款利率下调启动:3年期、5年期均下调0.25个百分点
  • 最高法:依法惩治损害民营企业合法权益的串通投标行为
  • 南宁海关辟谣网传“查获600公斤稀土材料”:实为焊锡膏
  • 种植耐旱作物、启动备用水源,甘肃各地多举措应对旱情