0
点赞
收藏
分享

微信扫一扫

同余问题(1)

沪钢木子 2022-08-09 阅读 160


同余:

同余问题(1)_i++

,当且仅当

同余问题(1)_i++_02

即a,b模m同余。

同余问题基础定理:

如果a,b,c是整数,m是正整数,且

同余问题(1)_同余_03

那么有:

同余问题(1)_ios_04

  ; 

同余问题(1)_i++_05



设a,b,c,d是整数,m是正整数,如果

同余问题(1)_同余_06


同余问题(1)_同余_07

,有:

同余问题(1)_i++_08

  ,

同余问题(1)_#include_09

。同余的对称性:

同余问题(1)_同余_10

同余的传递性:if a,b and c are integers with

同余问题(1)_ios_11


推导:

同余问题(1)_i++_12




取模mod和取余%的区别:前者的结果符号和mod后的数字一样,后者的结果符号和%前的数字一样。


例如:-8%7=-1 (计算机程序直接输出-1)


-8 mod 7= 6 


8%-7=1 


8 mod -7=-6

简单的模同余问题:

​​http://poj.org/problem?id=2115​​

poj C Looooops(同余方程)

大意:问for (variable = A; variable != B; variable += C)statement; 的A,B,C在mod(2^k)下经过几次能执行完,不能满足终止退奥简单的话就输出forever.

由题意可以列出等式:

同余问题(1)_ios_13


同余问题(1)_i++_14


同余问题(1)_同余_15


拓展欧几里得求出最小的执行次数x。


#include <iostream>
#include <cstdio>
using namespace std;
typedef long long LL;
void exgcd(LL a,LL b,LL &d,LL &x,LL &y){
if(b==0){
x=1; y=0; d=a;
return ;
}
exgcd(b,a%b,d,y,x);
y=y-(a/b)*x;
}
int main()
{
//freopen("cin.txt","r",stdin);
LL a,b,c,k;
while((cin>>a>>b>>c>>k)&&(a+b+c+k)){
LL aa=c,bb=(LL)1<<k,cc=b-a,d,x,y; //1必须先转化过来
exgcd(aa,bb,d,x,y);
bool has=1;
if(cc%d) has=0;
x=(x+bb)%bb;
x=x*(cc/d);
LL t=bb/d;
x=(x%t+t)%t; //运算次数不超过bb/d次,不然会超过1<<k。
if(!has) puts("FOREVER");
else printf("%lld\n",x);
}
return 0;
}


http://poj.org/problem?id=2769​​

pku  2769  Reduced ID Numbers(同余)

核心语句: For each group, she wants to find the smallest positive integer m, such that within the group all SINs reduced modulo m are unique.


Sample Input

2
1
124866
3
124866
111111
987651

Sample Output

1
8

注意本题可能超时的部分,要巧妙的清空数据hash思想,不能直接用memset。

TLE ||-_-


#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=1e6+5;
int a[305];
bool f[maxn];
int main()
{
//freopen("cin.txt","r",stdin);
int t,n;
cin>>t;
while(t--){
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
if(n==1) { puts("1"); continue ;}
int k;
for(k=2;;k++){
bool find=1;
memset(f,0,sizeof(f));
for(int i=0;i<n;i++){
if(f[a[i]%k]){ find=0; break; }
f[a[i]%k]=1;
}
if(find) break;
}
printf("%d\n",k);
}
return 0;
}


修改后:


#include <iostream>
#include <cstdio>
#include <cstring> //直接使用memset超时。
using namespace std;
const int maxn=1e6+5;
int a[305];
int que[305],top;
bool f[maxn];
void clear(){
for(int i=0;i<top;i++){
f[que[i]]=0;
}
}
int main()
{
//freopen("cin.txt","r",stdin);
int t,n;
cin>>t;
while(t--){
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
int k;
for(k=1;;k++){
bool find=1;
//memset(f,0,sizeof(f));
clear();
top=0;
for(int i=0;i<n;i++){
if(f[a[i]%k]){ find=0; break; }
que[top++]=a[i]%k;
f[a[i]%k]=1;
}
if(find) break;
}
printf("%d\n",k);
}
return 0;
}







举报

相关推荐

0 条评论