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[1]x[3]…x[k]x[2]
∴
原
式
=
x
[
1
]
x
[
3
]
…
x
[
k
]
x
[
2
]
然后进行约分即可
如果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
通过推结论,我发现答案就是
2n−2
2
n
−
2
你可以这么想:对于每一个位置上的数,假设已保证它左边的序列和右边的序列都具有单调性,那么它只有两种可能——一种是根据左边的序列进行单调,另一种是根据右边的序列进行单调,这就有了
2n
2
n
种可能。但在序列的一头一尾上,各只有一种可能,所以要
−2
−
2
#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<y
x
<
y
,则有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;
}