返回顶部

Panasonic Programming Contest (AtCoder Beginner Contest 186) E.Throne (数学,线性同余方程)

  • 题意:有围着一圈的\(N\)把椅子,其中有一个是冠位,你在离冠位顺时针\(S\)把椅子的位置,你每次可以顺时针走\(K\)个椅子,问最少要走多少次才能登上冠位,或者走不到冠位.
  • 题解:这题和洛谷那个青蛙🐸的约会简直一模一样啊,我们可以把圆看成是一条直线,我每次都向前都\(k\)步,多出\(N\)的部分我们可以对\(N\)取模,直到走到目标点.假设我们要走\(x\)次,那么\(Kx\equiv\ (N-S)\ mod\ N\),接下来就是线性同余方程求最小正整数解的板子了,关于线性同余方程的求解可以看我的上一篇博客,里面有详细的说明:
    https://www.cnblogs.com/lr599909928/p/14163525.html
  • 代码:
#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define me memset
#define rep(a,b,c) for(int a=b;a<=c;++a)
#define per(a,b,c) for(int a=b;a>=c;--a)
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}

#define int long long

int t;
int n,s,k;

int exgcd(int a,int b,int &x1,int &y1){
	int x2,y2;
	if(b==0){
		x1=1,y1=0;
		return a;
	}
	int d=exgcd(b,a%b,x2,y2);
	x1=y2,y1=x2-a/b*y2;
	return d;
}

signed main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>t;
	while(t--){
		int x1,y1;
		cin>>n>>s>>k;

		int d=exgcd(k,n,x1,y1);

		if(s%d) {cout<<-1<<'\n';continue;}
		
		s/=d,n/=d;
		x1*=-s;

		if(x1>=0) cout<<x1%n<<'\n';
		else cout<<(x1%n+n)%n<<'\n';
		
	}

    return 0;
}


posted @ 2020-12-20 15:11  Rayotaku  阅读(200)  评论(0编辑  收藏  举报