poj—2115:
题意大概是给你a,b,c,k,求解方程cx-2的k次*m=b-a;典型的扩展欧几里得求解最小x题
下面是代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<set>
#include<string.h>
#include<vector>
using namespace std;
typedef long long ll;
const int N=5e7+5;
ll gcd(ll a,ll b){
if(b==0)return a;
return gcd(b,a%b);
}
ll exgcd(ll a,ll b,ll &x,ll &y){
if(b==0){
x=1;
y=0;
return a;
}
ll m=exgcd(b,a%b,y,x);
y-=(a/b)*x;
return m;
}
int main(){
ll a,b,c,k;
while(cin>>a>>b>>c>>k){
if(a==0&&b==0&&c==0&&k==0)break;
if(b==a){
cout<<"0"<<endl;
continue;
}
ll C=b-a;
ll A=c;
ll B=1ll<<k,x,y;//这里表示2的k次
exgcd(A,B,x,y);
if(C%gcd(A,B)){
cout<<"FOREVER"<<endl;
continue;
}
x=x*C/gcd(A,B);
ll s=B/gcd(A,B);
cout<<(x%s+s)%s<<endl;
}
return 0;
}
做这道题是帮忙回顾一下exgcd的知识点及原理,也学到了2的k次的表达方式:1ll<<k (ll 为longlong)
约数和定理:
对于一个大于1正整数n可以分解质因数:n=p1^a1*p2^a2*p3^a3*…*pk^ak,
则由约数个数定理可知n的正约数有(a₁+1)(a₂+1)(a₃+1)…(ak+1)个,
那么n的(a₁+1)(a₂+1)(a₃+1)…(ak+1)个正约数的和为
f(n)=(p1^0+p1^1+p1^2+…p1^a1)(p2^0+p2^1+p2^2+…p2^a2)…(pk^0+pk^1+pk^2+…pk^ak)
定理证明
证明:若n可以分解质因数:n=p1^a1*p2^a2*p3^a3*…*pk^ak,
可知p1^a1的约数有:p1^0, p1^1, p1^2......p1^a1
…
同理可知,pk^ak的约数有:pk^0, pk^1, pk^2......pk^ak ;
实际上n的约数是在p1^a1、p2^a2、...、pk^ak每一个的约数中分别挑一个相乘得来,
可知共有(a₁+1)(a₂+1)(a₃+1)…(ak+1)种挑法,即约数的个数。
由乘法原理可知它们的和为
f(n)=(p1^0+p1^1+p1^2+…p1^a1)(p2^0+p2^1+p2^2+…p2^a2)…(pk^0+pk^1+pk^2+…pk^ak)