同余: ,当且仅当 即a,b模m同余。
同余问题基础定理:
设a,b,c,d是整数,m是正整数,如果 , ,有: ,。
同余的对称性:
同余的传递性:if a,b and c are integers with
#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; }
Sample Input
2
1
124866
3
124866
111111
987651
Sample Output
1
8
注意本题可能超时的部分,要巧妙的清空数据hash思想,不能直接用memset。#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; }