Newcoder 143 B.div(数论+高精度)

本文探讨了如何求解特定数论条件下的最小好数,通过分析数学特性转化为求解两个数论序列,并使用高精度算法实现。适用于数学竞赛及算法研究。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

定义nnn是好的当且仅当存在x∈[n2+1,n2+2n]x\in [n^2+1,n^2+2n]x[n2+1,n2+2n]满足x∣n4x|n^4xn4,给出一整数mmm,求不小于mmm的最小的好数nnn

Input

一个整数m(1≤m≤101000)m(1\le m\le 10^{1000})m(1m101000)

Output

输出不小于mmm的最小的好数nnn

Sample Input

4

Sample Output

6

Solution

假设n2+a∣n4n^2+a|n^4n2+an4,那么有n2+a∣(n4−(n2+a)(n2−a))=a2n^2+a|(n^4-(n^2+a)(n^2-a))=a^2n2+a(n4(n2+a)(n2a))=a2,但注意到a2≤4n2&lt;4(n2+a)a^2\le 4n^2&lt;4(n^2+a)a24n2<4(n2+a),故有a2=t(n2+a),t=1,2,3a^2=t(n^2+a),t=1,2,3a2=t(n2+a),t=1,2,3

1.t=11.t=11.t=1时,则a(a−1)=n2a(a-1)=n^2a(a1)=n2,无解

2.t=22.t=22.t=2时,则a2=2n2+2aa^2=2n^2+2aa2=2n2+2a,也即(a−1)2−2n2=1(a-1)^2-2n^2=1(a1)22n2=1,考虑椭圆曲线x2−2y2=1x^2-2y^2=1x22y2=1,初始解为(1,0),(3,2)(1,0),(3,2)(1,0),(3,2),故通解为a0=0,a1=2,ak+2=6ak+1−aka_0=0,a_1=2,a_{k+2}=6a_{k+1}-a_ka0=0,a1=2,ak+2=6ak+1ak

3.t=33.t=33.t=3时,则a2=3n2+3aa^2=3n^2+3aa2=3n2+3a,由于3∣a(a−3)3|a(a-3)3a(a3),故3∣a3|a3a,进而3∣n3|n3n,假设a=3b,n=3ma=3b,n=3ma=3b,n=3m,那么有9b2=27m2+9b9b^2=27m^2+9b9b2=27m2+9b,也即(2b−1)2−12n2=1(2b-1)^2-12n^2=1(2b1)212n2=1,考虑椭圆曲线x2−12y2=1x^2-12y^2=1x212y2=1,初始解为(1,0),(7,2)(1,0),(7,2)(1,0),(7,2),故通解为b0=0,b1=6,bk+2=14bk+1−bkb_0=0,b_1=6,b_{k+2}=14b_{k+1}-b_kb0=0,b1=6,bk+2=14bk+1bk

直接求出两个序列即得到所有的解,mmm比较大用高精度即可

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=300;
struct BigInt
{
	const static int mod=10000;
	const static int LEN=4;
	int a[maxn],len;
	BigInt() 
	{
		memset(a,0,sizeof(a));
		len=1;
	}
	void init(int x)
	{
		memset(a,0,sizeof(a));
		len=0;
		do
		{
			a[len++]=x%mod;
			x/=mod;
		}while(x);
	}
	void Init(const char s[])
	{
		memset(a,0,sizeof(a));
		int l=strlen(s),res=0;
		len=l/LEN;
		if(l%LEN)len++;
		for(int i=l-1;i>=0;i-=LEN)
		{
			int t=0,k=max(i-LEN+1,0);
			for(int j=k;j<=i;j++)t=t*10+s[j]-'0';
			a[res++]=t;
		}
	}
	int Compare(const BigInt &b)
	{
		if(len<b.len)return -1;
		if(len>b.len)return 1;
		for(int i=len-1;i>=0;i--)
			if(a[i]<b.a[i])return -1;
			else if(a[i]>b.a[i])return 1;
		return 0;
	}
	BigInt operator +(const BigInt &b)const
	{
		BigInt ans;
		ans.len=max(len,b.len);
		for(int i=0;i<=ans.len;i++)ans.a[i]=0;
		for(int i=0;i<ans.len;i++)
		{
			ans.a[i]+=((i<len)?a[i]:0)+((i<b.len)?b.a[i]:0);
			ans.a[i+1]+=ans.a[i]/mod;
			ans.a[i]%=mod;
		}
		if(ans.a[ans.len]>0)ans.len++;
		return ans;
	}
	BigInt operator -(const BigInt &b)const
	{
		BigInt ans;
		ans.len=len;
		int k=0;
		for(int i=0;i<ans.len;i++)
		{
			ans.a[i]=a[i]+k-b.a[i];
			if(ans.a[i]<0)ans.a[i]+=mod,k=-1;
			else k=0;			
		}
		while(ans.a[ans.len-1]==0&&ans.len>1)ans.len--;
		return ans;
	}
	BigInt operator *(const BigInt &b)const
	{
		BigInt ans;
		for(int i=0;i<len;i++)
		{
			int k=0;
			for(int j=0;j<b.len;j++)
			{
				int temp=a[i]*b.a[j]+ans.a[i+j]+k;
				ans.a[i+j]=temp%mod;
				k=temp/mod;
			}
			if(k!=0)ans.a[i+b.len]=k;
		}
		ans.len=len+b.len;
		while(ans.a[ans.len-1]==0&&ans.len>1)ans.len--;
		return ans;
	}
	BigInt operator /(const int &n)const
	{
		BigInt ans;
		ans.len=len;
		int k=0;
		for(int i=ans.len-1;i>=0;i--)
		{
			k=k*mod+a[i];
			ans.a[i]=k/n;
			k=k%n;
		}
		while(ans.a[ans.len-1]==0&&ans.len>1)ans.len--;
		return ans;
	}
	void output()
	{
		printf("%d",a[len-1]);
		for(int i=len-2;i>=0;i--)
			printf("%04d",a[i]);
		printf("\n");
	}
};
char s[1005];
BigInt t6,t14,a[3],b[3],c,d;
int main()
{
    scanf("%s",s);
    c.Init(s);
   	a[0].init(0),a[1].init(2);
   	b[0].init(0),b[1].init(6);
   	t6.init(6);
   	t14.init(14);
   	for(int i=1;;i++)
   	{
   		if(i>1)a[i%3]=a[(i+2)%3]*t6-a[(i+1)%3];
   		if(a[i%3].Compare(c)>=0)
   		{
   			d=a[i%3];
   			break;
   		}
   	}
   	for(int i=1;;i++)
   	{
   		if(i>1)b[i%3]=b[(i+2)%3]*t14-b[(i+1)%3];
   		if(b[i%3].Compare(c)>=0)
   		{
   			if(d.Compare(b[i%3])>0)d=b[i%3];
   			break;
   		}
   	}
   	d.output();
   	return 0;
}

资源下载链接为: https://pan.quark.cn/s/f989b9092fc5 今天给大家分享一个关于C#自定义字符串替换方法的实例,希望能对大家有所帮助。具体介绍如下: 之前我遇到了一个算法题,题目要求将一个字符串中的某些片段替换为指定的新字符串片段。例如,对于源字符串“abcdeabcdfbcdefg”,需要将其中的“cde”替换为“12345”,最终得到的结果字符串是“ab12345abcdfb12345fg”,即从“abcdeabcdfbcdefg”变为“ab12345abcdfb12345fg”。 经过分析,我发现不能直接使用C#自带的string.Replace方法来实现这个功能。于是,我决定自定义一个方法来完成这个任务。这个方法的参数包括:原始字符串originalString、需要被替换的字符串片段strToBeReplaced以及用于替换的新字符串片段newString。 在实现过程中,我首先遍历原始字符串,查找需要被替换的字符串片段strToBeReplaced出现的位置。找到后,就将其替换为新字符串片段newString。需要注意的是,在替换过程中,要确保替换操作不会影响后续的查找和替换,避免遗漏或重复替换的情况发生。 以下是实现代码的大概逻辑: 初始化一个空的字符串result,用于存储最终替换后的结果。 使用IndexOf方法在原始字符串中查找strToBeReplaced的位置。 如果找到了,就将originalString中从开头到strToBeReplaced出现位置之前的部分,以及newString拼接到result中,然后将originalString的查找范围更新为strToBeReplaced之后的部分。 如果没有找到,就直接将剩余的originalString拼接到result中。 重复上述步骤,直到originalStr
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值