4.14~4.20數論①
阿新 • • 發佈:2018-12-08
gcd和lcm
一行GCD
int gcd(int a,int b){return b==0 ? a:gcd(b,a%b);}
二進位制演算法
inline int GCD(int x,int y)
{
int i,j;
if(!x)return y;
if(!y)return x;
for(int i=0;0==(x&1);++i)x>>=1;
//0==(x&1)用來判斷x二進位制下最右邊一位是否為0
for(int j=0;0==(y&1);++j)y>>=1;
if(j<i)i=j;//i表示二進位制下右數連續的0的個數
while(1)
{
if(x<y)x^=y,y^=x,x^=y;
if(0==(x-=y))return y<<i;//y要乘原來除掉的2
while(0==(x&1))x>>=1;
}
}
除法表示式
我們可以發現,x[2]這個數總會在分母裡出現
其他x都可以在分子裡出現
然後進行約分即可
如果x[2]約到最後不為1,說明不可以
#include<bits/stdc++.h>
using namespace std;
string s;
long long temp,a[100010],s1=1,s2,g;
long long Gcd(long long x,long long y)
{
return (y==0)?x:Gcd(y,x%y);
}
int main()
{
getline(cin,s);
for (int i=0;i<s.size();++i)
{
temp++;
while (s[i]!='/'&&i<s.size())
{
a[temp]=a[temp]*10+s[i]-'0';
i++;
}
}
s2=a[2];
for (int i=1;i<=temp;++i)
{
if (i==2) continue;
g=Gcd(a[i],a[2]);
s1*=a[i]/g;
s2/=g;
if (s2==1)
{
printf("YES\n");
return 0;
}
}
printf("NO\n");
return 0;
}
同餘和擴歐
快速冪
long long qpow(long long x,long long a){
long long times=1,base=x,ans=1;
while(times<=a){
if(times&a){
ans*=base;
ans%=mod;
}
times<<=1;
base*=base;
base%=mod;
}
return ans;
}
快速乘
typedef long long ll;
ll mul(ll x,ll y)
{
return ((x*y-(ll)(((long double)x*y+0.5)/mod)*mod)%mod+mod)%mod;
}
擴歐
long long a,b;
struct Triple {
long long d,x,y;
};
Triple exgcd(long long a,long long b) {
if(b==0) {
return (Triple){a,1,0};
}
Triple t=exgcd(b,a%b);
return (Triple){t.d,t.y,t.x-a/b*t.y};
}
contest
通過推結論,我發現答案就是
你可以這麼想:對於每一個位置上的數,假設已保證它左邊的序列和右邊的序列都具有單調性,那麼它只有兩種可能——一種是根據左邊的序列進行單調,另一種是根據右邊的序列進行單調,這就有了
種可能。但在序列的一頭一尾上,各只有一種可能,所以要
#include<bits/stdc++.h>
using namespace std;
long long n,p,ans;
long long mul(long long x,long long y)
{
return ((x*y-(long long)(((long double)x*y+0.5)/p)*p)%p+p)%p;
}
long long qpow(long long x,long long a)
{
long long times=1,base=x,ans=1;
while (times<=a)
{
if (times&a)
{
ans=mul(ans,base);
ans%=p;
}
times<<=1;
base=mul(base,base);
base%=p;
}
return ans;
}
int main()
{
while (scanf("%lld %lld",&n,&p)!=EOF)
{
if (n==1) ans=1;
else ans=(qpow(2,n)-2+p)%p;
printf("%lld\n",ans);
}
return 0;
}
青蛙的約會
設走了t天
令
,則有x+mt=y+nt+kL
我們需要求解t的正整數解
直接擴歐
#include<bits/stdc++.h>
using namespace std;
long long x,y,m,n,l;
struct Triple
{
long long d,x,y;
};
inline int read()
{
int num=0,flag=1;
char c=getchar();
for (;c<'0'||c>'9';c=getchar())
if (c=='-') flag=-1;
for (;c>='0'&&c<='9';c=getchar())
num=(num<<3)+(num<<1)+c-48;
return num*flag;
}
Triple exgcd(long long a,long long b)
{
if (b==0)
{
return (Triple){a,1,0};
}
Triple t=exgcd(b,a%b);
return (Triple){t.d,t.y,t.x-a/b*t.y};
}
int main()
{
x=read();
y=read();
m=read();
n=read();
l=read();
if (x>y)
{
swap(x,y);
swap(m,n);
}
Triple t=exgcd(n-m,l);
if ((x-y)%t.d!=0)
{
printf("Impossible\n");
return 0;
}
t.x=t.x*(x-y)/t.d;
t.x=(t.x%l+l)%l;
printf("%lld\n",t.x);
return 0;
}