数论热血实战
1.
题目:https://vjudge.net/contest/316798#problem/P
codes:
#include<iostream>
#include<cmath>
#include<algorithm>
int s[1000005];
using namespace std;
int main()
{
int m,k;//欲求第k个与m互质的整数 kth GCD(s[k] ,m)==1
while(cin>>m>>k)
{
int i;
int num=0;
for(i=1;i<=m;i++)
{
if(__gcd(m,i)==1) s[num++]=i; //num是小于m且与m互质的正整数的个数
}
if(k%num==0) cout<<(k/num-1)*m+s[num-1]<<endl;// s[num-1],m+s[num-1],2m+s[num-1],....
else cout<<k/num*m+s[k%num-1]<<endl;// 不妨令k<num,s[k-1],m+s[k-1],2m+s[k-1],...
}
return 0;
}
参考:https://blog.csdn.net/huangshuai147/article/details/51277645
2.
题目:https://vjudge.net/contest/316798#problem/A
pre:
前进前之热身:
#include<iostream>
using namespace std;
int exgcd(int a,int b,int& x,int& y)//该用引用之处还是要用引用样子呀!
{
if(b==0)
{
x=1;
y=0;
return a;
}
int t=exgcd(b,a%b,x,y);//training!!
int x0=x;
int y0=y;
x=y0;
y=x0-(a/b)*y0;
return t;
}
int main()
{
int a,b,x,y,t;
cin>>a>>b;
t=exgcd(a,b,x,y);
cout<<t<<endl;
cout<<x<<" "<<y<<endl;
return 0;
}

解决方案可见于我的另一篇博客:《数论:扩展欧几里得》
3.
题目:https://vjudge.net/contest/316798#problem/B














Repeat:


在c是GCD(a,b)的倍数的情况下:

//左边之系数与右边放置之数具去同除!


...............
codes:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int exgcd(ll a,ll b,ll& x,ll& y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
ll t=exgcd(b,a%b,x,y);
ll x0=x;
ll y0=y;
x=y0;
y=x0-(a/b)*y0;
return t;
}
int main()
{
int t;
cin>>t;
while(t--)
{
ll c,d,a,b,x,y,x0,y0;//c为起点,d为终点;步长:a,b;
cin>>c>>d>>a>>b;
if(c>d) swap(c,d);
ll u=d-c;//距离
ll g=exgcd(a,b,x,y);//g=GCD(a,b),默认的那一组解所对应的方程右侧之值是为1!
if(u%g!=0)
{
cout<<-1<<endl;
continue;
}//从头再来
else
{
a/=g;
b/=g;
x*=(u/g);
y*=(u/g);
ll k=(y-x)/(a+b);
ll ans=1e18;
for(int i=k-1;i<=k+1;i++)
{
x0=x+i*b;
y0=y-i*a;
if(abs(x0)+abs(y0)==abs(x0+y0)) ans=min(ans,max(x0,y0));
else ans=min(ans,abs(x0)+abs(y0));
}
cout<<ans<<endl;
}
}
return 0;
}
/* int t=__gcd(a,b);
a/=t;b/=t;d/=t;
exgcd(a,b,x,y);
x=d*x;
y=d*y; */
浙公网安备 33010602011771号