题目

题目大意

求方程\((x^m-x)\mod n=0\)在整数范围\([1,n]\)的解的个数。

\(n=\sum_{i=1}^{c}p_i\)

给出\(c\)和\(p_i\)


思考历程

作为数论白痴,比赛时看到这题就想要自闭了……

乱推一波式子,后面的就不会搞了。

于是就想部分分……结果连部分分都没有想出来。

直接打了个\(20\)分的暴力。


正解

可以把方程拆成\(c\)个方程(对于每个\(i\)):\((x^m-x)\mod p_i=0\)

分别解出每个同余方程组。解的时候枚举\(x\),并将每个\(x^m\)处理出来。

快速幂会TLE,所以要用积性筛的方式来求\(x^m\)。具体来说,函数\(f(x)=x^m\)是个积性函数。所以用快速幂求出\(x\)为质数时的\(x^m\),合数就是两个因数的函数值乘起来。

这样时间复杂度是可以过的。

处理出来之后,每个同余方程的解的个数的乘积就是整个同余方程组的解的个数。

证明;

对于方程\((x^m-x)\mod p_i=0\),设解为\(x_{i,1},x_{i,2},...,x_{i,s_i}\)

每个方程分别抽出一个解来,记作\(x_i\),\(x_i\)为\(x_{i,1..s_i}\)中的一个解。

设方程组的解为\(X\)

那么这个\(X\)满足以下方程组(对于每个\(i\)):

\(X \equiv x_i (\mod p_i)\)

根据中国剩余定理,这个方程组只会有一个解。

方程组的解和\(x_1,x_2,..,x_c\)的取值是一一对应的(这个可以感性理解)。

对于\(x_i\),有\(s_i\)种可能的取值。根据乘法原理,同余方程组解的个数即为每个同余方程的解的个数的乘积。

后来我知道了一个更加强大的方法。

同样是求\((x^m-x)\mod p_i=0\)的解的个数,然而这次不用暴力求。

有个性质:解的个数等于\(\gcd(m-1,p_i-1)+1\)

(为了方便,后面直接将\(p_i\)的下标省略。)

证明:

原式可以写成\(x^m\equiv x(\mod p)\)

\(p=2\)的时候显然成立。

\(x=0\)显然是方程的解

考虑解在区间\([1,p-1]\)的取值

由于\(p\)为奇素数,所以一定有原根。设原根为\(g\)

方程可以表示为\(g^{ym}\equiv g^y (\mod p)\)

由费马小定理得\(ym\equiv y (\mod (p-1))\)

也就是\(y(m-1) \equiv 0 (\mod (p-1))\)

设\(k=\gcd(m-1,p-1)\)。两边同时除以\(k\)得\(y\frac{m-1}{k}\equiv 0 (\mod \frac{p-1}{k})\)

由于\(\gcd(\frac{m-1}{k},\frac{p-1}{k})=1\),所以\(\frac{p-1}{k}|y\)

所以\(y\)为\(\frac{p-1}{k}\)的倍数,显然可以取\(0\)到\(k-1\)倍,也就是说\(y\)有\(k\)个解。

所以\(x\)也有\(k\)个解。

所以解的个数为\(\gcd(m-1,p_i-1)+1\)

有了这条性质,程序就快得飞起了(爆踩标程)……


代码

暴力求解:

(反正数据范围这么小,就懒得打线筛了。埃氏筛法的常数小一些)

  1. using namespace std;
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. #define mo 998244353
  6. #define P 10000
  7. int id;
  8. int c,m;
  9. int n;
  10. inline int my_pow(int x,int y,int p){
  11. int res=1;
  12. for (;y && res;y>>=1,x=x*x%p)
  13. if (y&1)
  14. res=res*x%p;
  15. return res;
  16. }
  17. int di[P+1];
  18. int xm[P+1];
  19. inline void init(){
  20. di[1]=1;
  21. for (register int i=2;i<=P;++i){
  22. if (di[i])
  23. continue;
  24. di[i]=i;
  25. for (int j=i*i;j<=P;j+=i)
  26. di[j]=i;
  27. }
  28. }
  29. inline int work(int p){
  30. int res=2;
  31. xm[0]=0,xm[1]=1;
  32. for (register int i=2;i<=p;++i){
  33. xm[i]=(di[i]==i?my_pow(i,m,p):xm[i/di[i]]*xm[di[i]]%p);
  34. res+=(xm[i]==i);
  35. }
  36. return res;
  37. }
  38. int main(){
  39. freopen("division.in","r",stdin);
  40. freopen("division.out","w",stdout);
  41. int T;
  42. scanf("%d%d",&id,&T);
  43. init();
  44. while (T--){
  45. scanf("%d%d",&c,&m);
  46. long long ans=1;
  47. for (int i=1;i<=c;++i){
  48. int p;
  49. scanf("%d",&p);
  50. ans=ans*work(p)%mo;
  51. }
  52. printf("%lld\n",ans);
  53. }
  54. return 0;
  55. }

牛逼解法:

  1. using namespace std;
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. #define mo 998244353
  6. inline int gcd(int a,int b){
  7. int k;
  8. while (b){
  9. k=a%b;
  10. a=b;
  11. b=k;
  12. }
  13. return a;
  14. }
  15. int main(){
  16. freopen("division.in","r",stdin);
  17. freopen("division.out","w",stdout);
  18. int T;
  19. scanf("%*d%d",&T);
  20. while (T--){
  21. int c,m;
  22. scanf("%d%d",&c,&m);
  23. long long ans=1;
  24. while (c--){
  25. int p;
  26. scanf("%d",&p);
  27. ans=ans*(gcd(p-1,m-1)+1)%mo;
  28. }
  29. printf("%lld\n",ans);
  30. }
  31. return 0;
  32. }

总结

看来我的数论还是太菜了……QWQ……

[JZOJ6272] 2019.8.4【NOIP提高组A】整除的更多相关文章

  1. NOIP提高组2004 合并果子题解

    NOIP提高组2004 合并果子题解 描述:在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消 ...

  2. 计蒜客 NOIP 提高组模拟竞赛第一试 补记

    计蒜客 NOIP 提高组模拟竞赛第一试 补记 A. 广场车神 题目大意: 一个\(n\times m(n,m\le2000)\)的网格,初始时位于左下角的\((1,1)\)处,终点在右上角的\((n, ...

  3. 1043 方格取数 2000 noip 提高组

    1043 方格取数  2000 noip 提高组 题目描述 Description 设有N*N的方格图(N<=10,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0.如下图所示(见样 ...

  4. [NOIP提高组2018]货币系统

    [TOC] 题目名称:货币系统 来源:2018年NOIP提高组 链接 博客链接 CSDN 洛谷博客 洛谷题解 题目链接 LibreOJ(2951) 洛谷(P5020) 大视野在线评测(1425) 题目 ...

  5. NOIP提高组初赛难题总结

    NOIP提高组初赛难题总结 注:笔者开始写本文章时noip初赛新题型还未公布,故会含有一些比较老的内容,敬请谅解. 约定: 若无特殊说明,本文中未知数均为整数 [表达式] 表示:在表达式成立时它的值为 ...

  6. 津津的储蓄计划 NOIp提高组2004

    这个题目当年困扰了我许久,现在来反思一下 本文为博客园ShyButHandsome的原创作品,转载请注明出处 右边有目录,方便快速浏览 题目描述 津津的零花钱一直都是自己管理.每个月的月初妈妈给津津\ ...

  7. 2018.12.30【NOIP提高组】模拟赛C组总结

    2018.12.30[NOIP提高组]模拟赛C组总结 今天成功回归开始做比赛 感觉十分良(zhōng)好(chà). 统计数字(count.pas/c/cpp) 字符串的展开(expand.pas/c ...

  8. 2018.12.08【NOIP提高组】模拟B组总结(未完成)

    2018.12.08[NOIP提高组]模拟B组总结 diyiti 保留道路 进化序列 B diyiti Description 给定n 根直的木棍,要从中选出6 根木棍,满足:能用这6 根木棍拼出一个 ...

  9. 2013 Noip提高组 Day2

    3288积木大赛 正文 题目描述 春春幼儿园举办了一年一度的“积木大赛”.今年比赛的内容是搭建一座宽度为n的大厦,大厦可以看成由n块宽度为1的积木组成,第i块积木的最终高度需要是hi. 在搭建开始之前 ...

  10. 2013 Noip提高组 Day1

    3285 转圈游戏 2013年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description ...

随机推荐

  1. touchWX使用 echarts

    <button bindtap="init" wx:if="{{!isLoaded}}">加载图表</button> <butto ...

  2. 实现简单的PHP接口,以及使用js/jquery ajax技术调用此接口

    主要介绍下如何编写简单的php接口,以及使用js/jquery的ajax技术调用此接口. Php接口文件(check.php): <?php $jsonp_supporter = $_GET[‘ ...

  3. windows server 2012 安装完只有命令行

    今天在安装完windows server 2012 只有命令行,发现没有桌面.然后在别人的提醒下,才发现忘记安装gui了,这个时候,我也懒的重新安装一遍,所以就在网上找如何能够解决问题的方法,下面为解 ...

  4. RedHat版本Linux安装chrome-stable配合chromeDriver进行自动化测试环境准备

    一.Linux机器安装google-chrome-stable 1.设置google-chrome软件源 sudo vim /etc/yum.repos.d/google-chrome.repo [g ...

  5. Spring常见面试题及答案解析

    .说一下spring中Bean的作用域 singleton: Spring IoC容器中只会存在一个共享的Bean实例,无论有多少个Bean引用它,始终指向同一对象.Singleton作用域是Spri ...

  6. 判断访问浏览器客户端类型(pc,mac,ipad,iphone,android)

    <script type="text/javascript"> //平台.设备和操作系统 var system = { win: false, mac: false, ...

  7. 更强大的实时数仓构建能力!分析型数据库PostgreSQL 6.0新特性解读

    阿里云 AnalyticDB for PostgreSQL 为采用MPP架构的分布式集群数据库,完备支持SQL 2003,部分兼容Oracle语法,支持PL/SQL存储过程,触发器,支持标准数据库事务 ...

  8. xcode5 添加Build Phases脚本

    http://www.runscriptbuildphase.com/ 版权声明:本文为博主原创文章,未经博主允许不得转载.

  9. 从yjz那里偷来的fread读入挂

    struct fastio{ char s[100005]; int it,len; fastio(){it=len=0;} inline char get(){ if(it<len)retur ...

  10. 关于Mysql分区和分表

    [分区概念]分区就是把一张表的数据按照一定的规则分成多个区块,这些区块可以在同一个磁盘上,也可以在不同的磁盘上.分区后表还是一张表.分区根据一定的规则把数据文件和索引文件进行了分割,还多出了一个.pa ...