Comet OJ - Contest #10 C 鱼跃龙门(质因数分解&扩展欧几里得)

Comet OJ - Contest #10 C 鱼跃龙门(质因数分解&扩展欧几里得)

题目大意

给定一个正整数 n,一共有 n 座龙门,跳过第 j (j<n) 座龙门将会到达第 j+1座龙门前,特殊地,跳过第 n座龙门后将会到达第 1 座龙门前。

胖头鱼一开始在第一座龙门前,接下来,第 i 个时刻内它会向前跳 i 次,每次跳过 1 座龙门,求最小的正整数 x 满足第 x 个时刻结束后胖头鱼恰好会回到起点。

解题思路

设跳动次数为i,则当 n ∣ i ( i + 1 ) 2 n|{i(i+1)\over 2} n2i(i+1)时满足条件,由此得出方程
{ p x − q y = 1 x ∗ y = 2 n \begin{cases} px-qy&amp;=1\\ x*y&amp;=2n \end{cases} {pxqyxy=1=2n
最小的i即最小的qy,由此得出答案

但实际上这题卡了 n \sqrt n n 的分解因数,因此需要先素数筛筛出所有的素数,然后实现 O ( n log ⁡ n ) O(\frac{n}{\log n}) O(lognn)分解

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int size=1e6+5;
bool prime[size];
int p[size],tol;
void init()
{
	for(int i=0;i<size;i++) prime[i]=true;
	for(int i=2;i<size;i++)
	{
		if(prime[i]) p[++tol]=i;
		for(int j=1;j<=tol&&i*p[j]<size;j++)
		{
			prime[i*p[j]]=false;
			if(i%p[j]==0) break;
		}
	}
}
inline LL exgcd(LL a,LL b,LL &x,LL &y){
    if(b == 0){
        x = 1,y = 0;
        return a;
    }
    LL g = exgcd(b,a%b,x,y);
    LL tep = x;
    x = y;
    y = tep-a/b*y;
    return g;
}
LL num[32],cnt[32];
int tot;
LL quick_pow(LL a,LL b){LL ans=1;while(b){if(b&1) ans=ans*a;a=a*a;b>>=1;} return ans;}
int main()
{
 	int t;
 	scanf("%d",&t);
 	init();
 	while(t--)
 	{
 		LL n;
 		scanf("%lld",&n);
 		n=n*2;
 		LL tmpn=n;
 		tot=0;
 		for(int i=1;i<=tol&&p[i]*p[i]<=n;i++)
 		{
 			if(n%p[i]==0)
 			{
 				num[++tot]=p[i];
 				cnt[tot]=0;
 				do{
 					cnt[tot]++;
 					n/=p[i];
 				}while(n%p[i]==0);
 			}
 		}
 		if(n!=1) {num[++tot]=n;cnt[tot]=1;}
 		for(int i=1;i<=tot;i++) num[i]=quick_pow(num[i],cnt[i]);
 		n=tmpn;
 		LL ans=2*n-1;
 		for(int i=0;i<(1<<tot);++i)
 		{
 			LL x=1;
 			for(int j=0;j<tot;++j)
 			{
 				if((1<<j)&i)
 					x=x*num[j+1];
			}
			LL y=n/x;
			LL p,q;
			LL r=exgcd(x,-y,p,q);
			q/=r;
			q%=x;
			if(q<=0) q+=x;
			ans=min(ans,q*y);
		}
		printf("%lld\n",ans);
	}
} 			
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值