Idempotents 数论

来源:互联网 发布:淘宝上卖宿舍用品的店 编辑:程序博客网 时间:2024/06/05 18:19

来源:http://acm.hust.edu.cn:8080/judge/contest/view.action?cid=9927#problem/H

题意:给你一个n,n是两个不同素数的乘积。让求小于等于n的x,满足x*x %n = x%n。

思路:其实就是求x * (x-1) 是n的倍数。我们可以把n分解成两个素数的乘积,即n = p * q,若x * (x - 1) 是n的倍数,则一定是通过p或者q的倍数得到的。我们假设是从p的倍数得到的,则x从p开始循环,若 x - 1 是q的倍数,则该x符合题意。同样的道理对于q也是一样的。这样的话,我们分别循环p和q的倍数即可。但是由于n比较大(10亿),所以普通方法肯定会超时。

其实这道题的正确方法是扩展欧几里得,但是我确实是完全忘了扩展欧几里得是怎么一回事,于是就想了个无耻的方法水过了。我的方法是:只循环max(p,q),循环的时候两个条件一起判断即可。由于max(p,q)最大在30000多,所以是可以水过的,跑了760ms,惭愧,,,

我的搓代码:

#include <iostream>#include <cstdio>#include <string.h>#include <algorithm>#include <set>#include <vector>#include <cmath>using namespace std;#define CLR(arr,val) memset(arr,val,sizeof(arr))const int N = 15;int dp[N][N],num[10],prime[100010],flag[100010],KK = 0;void init(){CLR(flag,0);for(int i = 2;i <= 100000;++i){if(!flag[i]){  flag[i] = 1;  prime[KK++] = i;  for(int j = i*2;j <= 100000;j+=i)  flag[j] = 1;}}}int main(){init();int numcase;scanf("%d",&numcase);while(numcase--){  int n,p,q;  CLR(num,0);  scanf("%d",&n);  for(int i = 0;i < KK;++i){  if(n % prime[i] == 0){    p = prime[i];q = n/prime[i];break;  }  }  int cnt = 2,k = 1;  int minpri = min(p,q);  int maxpri = max(p,q);  int initnum = (maxpri+1)/minpri,initmax = maxpri,initmin = minpri,mmax = maxpri;  while(maxpri < n){  if((maxpri + 1) % initmin == 0){    num[cnt++] = maxpri + 1;  }  if((maxpri - 1)% initmin == 0){    num[cnt++] = maxpri ;  }  maxpri += mmax;  } /* while(initmax < n){if((initmax-1) % initmin == 0){num[cnt++] = initmax;}        initmax += mmax;  }*/  num[0] = 0;num[1] = 1;  sort(num,num+cnt);  for(int i = 0;i < cnt-1;++i){    printf("%d ",num[i]);  }  printf("%d\n",num[cnt-1]);}return 0;}


原创粉丝点击