• JZOJ6272.【NOIP2019提高组A】整除


    Description

    传送门
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    Solution

    • n|xm-x等价于:任意p,满足 p|xm-x。p为质因子。
    • 将n的质因子p分开考虑。
    • 不难得出,在模p意义下满足以上条件的解y(y<p)。
    • 那么我们要求最终解x同时满足所有质因子条件,每一个质因子都可以选择一些解y中的一个并且要求x与y在模p意义下同余,那么这个条件肯定满足了。如果cnti表示对于第i个质因子y的个数,那么共有cnt1* cnt2 * cnt3…*cntc种方案。
    • 这样我们就可以得到其中一种方案的c条同余方程。
    • 根据中国剩余定理,我们可以知道,在模M(M=所有模数即质因子的乘积,在这里就是n)下,这些同余方程有且只有一个解。
    • 所以说一种同余方程的方案就对应着一个解。所以实际上解的个数就等于方案数cnt1* cnt2 * cnt3…*cntc。
    • 求质因子内满足条件的个数等同于求所有xm%p (x<p) ,可以线性求过去,即用x的最小质因子去更新它,跟筛phi很像。
    • 素数就直接快速幂。但是会被卡常,所以我们让m%(p-1),因为xp-1=1(mod p)

    update 还有一种更秀的做法,碾爆正解

    source%%%

    在这里插入图片描述

    我的辣鸡代码

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #define ll long long 
    #define mo 998244353
    #define maxp 10005
    using namespace std;
    
    int id,T,c,m,mm,i,j,k,p;
    int tot,pri[maxp],bz[maxp],f[maxp];
    ll ans,cnt;
    
    int ksm(int x,int y){
    	ll s=1;
    	for(;y;y/=2,x=x*x%p) if (y&1)
    		s=s*x%p;
    	return s;
    }
    
    int main(){
    	for(i=2;i<maxp;i++) {
    		if (!bz[i]) pri[++tot]=i;
    		for(j=1;j<=tot&&i*pri[j]<maxp;j++) {
    			bz[i*pri[j]]=i;
    			if (i%pri[j]==0) break;
    		}
    	}	
    	
    	scanf("%d",&id);
    	scanf("%d",&T);
    	while (T--){
    		scanf("%d%d",&c,&m);
    		ans=1;
    		while (c--){
    			scanf("%d",&p);
    			cnt=2,mm=m%(p-1);
    			for(i=2;i<p;i++) {
    				f[i]=bz[i]?f[bz[i]]*f[i/bz[i]]%p:ksm(i,mm);
    				cnt+=(f[i]==i);
    			}
    			ans=ans*cnt%mo;
    		}
    		printf("%lld
    ",ans);
    	}	
    }
    

    数论大佬的做法

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #define ll long long 
    #define mo 998244353
    #define maxp 10005
    using namespace std;
    
    int id,T,c,m,mm,i,j,k,p;
    ll ans,cnt;
    
    int gcd(int x,int y){
    	return (x%y==0)?y:gcd(y,x%y);
    }
    
    int main(){
    	scanf("%d",&id);
    	scanf("%d",&T);
    	while (T--){
    		scanf("%d%d",&c,&m);
    		ans=1;
    		while (c--){
    			scanf("%d",&p);
    			ans=1ll*ans*(gcd(m-1,p-1)+1)%mo;
    		}
    		printf("%lld
    ",ans);
    	}	
    }
    
  • 相关阅读:
    慕课网-安卓工程师初养成-6-3 如何使用 Java 中的数组
    慕课网-安卓工程师初养成-6-2 练习题
    慕课网-安卓工程师初养成-6-1 什么是数组
    慕课网-安卓工程师初养成-5-5 进阶练习
    慕课网-安卓工程师初养成-5-4 使用 Eclipse 调试程序
    慕课网-安卓工程师初养成-5-3 编程练习优化
    慕课网-安卓工程师初养成-5-2 编程练习解析
    币种统计
    先取不败游戏
    贪心算法——数列操作得到最大的值
  • 原文地址:https://www.cnblogs.com/DeepThinking/p/11700911.html
Copyright © 2020-2023  润新知