数论专题

基础应用:
hdoj3501

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define ll __int64
#define mod 1000000007
ll phi(int n)
{
    int m = floor(sqrt(n+0.5));
    ll ans = n;
    for(int i = 2; i <= m; i++)
		if(n%i == 0)
		{
			ans = ans / i * (i-1);
			while(n%i == 0)
			{
				n /= i;
			}
		}
    if(n > 1)
		ans = ans / n *(n-1);
    return ans;
}
ll mulmod(ll a,ll n,ll m){
    ll y=0;
    a%=m;
    while(n){ 
        if(n&1) y+=a;
        if(y>=m) y-=m;
        n>>=1;
        a<<=1;
        if(a>=m) a-=m;
    }
    return y;
}

int main()
{
	int n,i;
	scanf("%d",&n);
	while(n!=0)
	{
		ll tmp=n-1-phi(n);
		if(tmp&1)
			n/=2;
		else
			tmp/=2;
		ll	ans=mulmod(tmp,(ll)n,(ll)mod);
		printf("%I64d\n",ans);
		
		

		scanf("%d",&n);
	}
	system("pause");
	return 0;
}

hdoj1215

#include<stdio.h>
#include<string.h>
#define N 500000
int sum[N+10];
void yueshu()
{
	int i,j;
	for(i=1;i<=N/2;i++)
	{
		for(j=2*i;j<=N;j+=i)
		{
			if(j>N) break;
			sum[j]+=i;
		}
	}
	return;

}
int main()
{
	int t;
	memset(sum,0,sizeof(sum));
	yueshu();
	scanf("%d",&t);
	while(t--)
	{
		int n;
		scanf("%d",&n);
		printf("%d\n",sum[n]);
		
	
	
	
	}
	return 0;
}

hdoj2136
用普通的筛选法筛出素数,然后记录每个素数在素数表里的位置,pr[]数组记录的是每个数的最大素因子
注意:这里的筛选素数不能写成

for(i=2;i*i<=N;i++)
{	
    if(!pr[i])
    {
	p[++lp]=i;
	pos[i]=lp;
	for(j=i*i;j<=N;j+=i)
	pr[j]=i;
    }
}

这样会出错,对于sqrt(N)的素数没有用来更新它的倍数,这样它的倍数的pr[]也没有更新,另外若i是素数,也没更新pr[i]

#include<stdio.h>
const int N=1000000;
int pr[N+10],p[N/10+10],lp;
int pos[N+10];
void gp(){
	int i,j;
    for(i=2;i<=N;i++)
	{	
		if(!pr[i])
		{
			p[++lp]=i;
			pos[i]=lp;
			for(j=i;j<=N;j+=i)
				pr[j]=i;
		}
    }
	return;
}
int main()
{
	int i,j;
	int n;
	gp();
	while(scanf("%d",&n)!=EOF)
	{
		if(n==1)
		{
			printf("0\n");
			continue;
		}
		
		printf("%d\n",pos[pr[n]]);
	
	
	}
	return 0;

}

poj2689
筛两次,注意细节

#include<stdio.h>
#include<string.h>
bool p[50010];
bool pr[1000000+10];
int prime[1000000+10];
void gp()
{
	int i,j;
	p[1]=0;
	memset(p,1,sizeof(p));
	for(i=2;i*i<=50000;i++)
	{
		if(p[i])
		{
			for(j=i*i;j<=50000;j+=i)
			{
				p[j]=0;
			}
		}
	}
	return;
}
void gp2(__int64 l,__int64 r)
{
	__int64 i,j;
	memset(pr,1,sizeof(pr));
	if(l==1)
		pr[1]=0;
	for(i=2;i*i<=r;i++)
	{
		if(i*i>r)
			break;
		if(p[i])
		{
			j=i*i;
			if(j<l)
			{
				j=(l/i)*i;
				if(j<l)
					j+=i;
			}
			for(;j<=r;j+=i)
			{
				if(j>r) break;
				pr[j-l+1]=0;
			}
		}
	}
	return;
}
int main()
{
	__int64 i;
	__int64 l,r;
	gp();
	while(scanf("%I64d %I64d",&l,&r)!=EOF)
	{
		gp2(l,r);
		int cnt=0;
		for(i=l;i<=r;i++)
		{
			if(pr[i-l+1])
				prime[++cnt]=i;
		}
		if(cnt<=1)
		{
			printf("There are no adjacent primes.\n");
			continue;
		}
		int min=1000000+10,max=-1,minx,miny,maxx,maxy;
		for(i=1;i<=cnt-1;i++)
		{
			if(prime[i+1]-prime[i]<min)
			{
				min=prime[i+1]-prime[i];
				minx=prime[i];
				miny=prime[i+1];
			
			}
			if(prime[i+1]-prime[i]>max)
			{
				max=prime[i+1]-prime[i];
				maxx=prime[i];
				maxy=prime[i+1];
			}
		
		}
		printf("%d,%d are closest, %d,%d are most distant.\n",minx,miny,maxx,maxy);
	
	}


	return 0;
}

hdoj4474
这题思路很巧妙,如果枚举n的倍数显然超时,而且这个答案可能非常大,无法用long long存储。
正确方法是用可用的数字bfs,如果当前状态下除以n的余数前面状态得到过,那么这个就不用进队了,因为显然由前面的那个状态进行搜索更优,这样队列中最多10000左右的元素,状态间要记录前驱。开始没有记录前驱,而是直接每个状态都开个字符串,最后MLE。。
然后又是被一个小错误弄的RE好多次。。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define maxn 10010
char use[11];
typedef struct node{
	char num;
	short mod;
	short pre;
}node;
bool has[maxn];
short n,m;
char cnt;
char ans[maxn];
node q[maxn];
short anscnt;
bool bfs()
{
	short i,j;
	memset(has,0,sizeof(has));
	int iq=0;
	node sr;
	for(i=1;i<=cnt;i++)
	{

		if(use[i]==0)
			continue;
		sr.mod=use[i]%n;
		if(has[sr.mod]==1) continue;
		has[sr.mod]=1;
		sr.pre=-1;
		sr.num=use[i];
		if(sr.mod==0)
		{
			ans[++anscnt]=use[i];
			return 1;
		}
		q[iq++]=sr;
	}
	for(i=0;i<=iq-1;i++)
	{
		int mod=q[i].mod;
		for(j=1;j<=cnt;j++)
		{
			int yushu=((mod*(10%n))%n+use[j]%n)%n;
			if(has[yushu]) continue;
			has[yushu]=1;
			node tmp;
			tmp.mod=yushu;
			tmp.pre=i;
			tmp.num=use[j];
			if(tmp.mod==0)
			{
				ans[++anscnt]=tmp.num;
				int cur=tmp.pre;
					while(cur!=-1)
					{
						ans[++anscnt]=q[cur].num;
						cur=q[cur].pre;
					}
				return 1;
			
			}
			q[iq++]=tmp;

		}
	}
	return 0;
}
int main()
{
	short i,j;
	int cases=0;
	while(scanf("%d %d",&n,&m)!=EOF)
	{
		if(m==10)
		{
			for(i=1;i<=m;i++)
			{
				char tmp;
				scanf("%d",&tmp);
			}
			printf("Case %d: ",++cases);
			printf("-1\n");

			continue;
		}
		bool digit[12];
		anscnt=0;
		memset(digit,1,sizeof(digit));
		for(i=1;i<=m;i++)
		{
			int tmp;
			scanf("%d",&tmp);
			digit[tmp]=0;
		}
		cnt=0;
		for(i=0;i<=9;i++)
		{
			if(digit[i]==1)
				use[++cnt]=i;
		}
		bool flag=bfs();
		printf("Case %d: ",++cases);
		if(flag)
		{
			for(int tt=anscnt;tt>=1;tt--)
				printf("%d",ans[tt]);
			printf("\n");
		}
		else
			printf("-1\n");


	
	
	}
	return 0;
}

poj1845
对a进行分解质因数,但是由于是a^b,所以a^b的质因子指数非常大,所以构造矩阵快速计算pi^1+pi^2+……+pi^ki %mod
矩阵为:
pi pi
0 1
开始的思路是O(n)时间预处理出2——50000000每个数的最小质因数,然后常数时间对a分解质因数,结果无情的MLE了。。
改成sqrt(n)时间分解质因数就能AC了

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
const int maxn=3100000;
const int mod=9901;
int cnt;
__int64 p[maxn],k[maxn];
void fenjie(int n)
{
	cnt=0;
	for(int i=2;i*i<=n;i++)
	{
		if(n%i == 0)
		{
			p[++cnt]=i;
			k[cnt]=0;
			while(n%i==0)
			{
				n/=i;
				k[cnt]++;
			}
		}
	}
	if(n > 1)
	{
		p[++cnt]=n;
		k[cnt]=1;
	}
	return;
}
typedef struct Mat{
	__int64 m[3][3];
}Mat;
Mat per;
Mat multi(Mat a,Mat b)
{
	int i,j,k;
	Mat ans;
	for(i=1;i<=2;i++)
		for(j=1;j<=2;j++)
		{
			__int64 tmp=0;
			for(k=1;k<=2;k++)
				tmp=(tmp+a.m[i][k]*b.m[k][j])%mod;
			ans.m[i][j]=tmp;	
		}
	return ans;

}
Mat pow(Mat a,__int64 k)
{
	Mat ans=per,p=a;
	while(k)
	{
		if(k&1)
		{
			k--;
			ans=multi(ans,p);
		}
		else
		{
			k/=2;
			p=multi(p,p);
		}
	}
	return ans;
}
int main()
{
	int i,j;
	int a,b;
	Mat aa;
	for(i=1;i<=2;i++)
		for(j=1;j<=2;j++)
			per.m[i][j]=(i==j);
	while(scanf("%d %d",&a,&b)!=EOF)
	{
		fenjie(a);
		__int64 ans=1;
		for(i=1;i<=cnt;i++)
		{
			k[i]*=b;
			aa.m[1][1]=p[i];aa.m[1][2]=p[i];aa.m[2][1]=0;aa.m[2][2]=1;
			Mat tmp=pow(aa,k[i]);
			__int64 tt=(tmp.m[1][2]+1)%mod;
			ans=(ans*tt)%mod;
		}
		printf("%I64d\n",ans);
	
	
	
	
	
	}

	return 0;
}

poj1061
在zxs大神的帮助下终于ac了,orz一下^_^
wa的关键点在于自己对求方程通解的原理原来并不理解深刻,只是生搬硬套,导致错误。理解很重要啊
设d=gcd(a,b)
ax+by=d的初解是(x,y),那么ax0-by0=0加到该方程上一定还是成立的(因为加了0嘛。。)得到:
a(x+x0)+b(y-y0)=d。ax0=by0,可见a是ax0的约数,b是ax0的约数,所以ax0=by0一定是a和b的公倍数,那么要不漏掉任何解的话ax0自然要取最小,即ax0=by0=lcm(a,b)(设为lcm).如此可见,通解为(x+k*(lcm/a),y-k*(lcm/b))
再来考虑ax+by=c与ax+by=d的关系,显然在后面那个方程两边乘上c/d就得到了方程ax+by=c.所以得到ax+by=c的初解是(x*c/d,y*c/d)。那么它的通解呢。我们可以用分析ax+by=d的通解的方法来分析。
在ax+by=c基础上加上ax0-by0=0方程仍然成立。由于从ax+by=d到ax+by=c,系数a、b没有变,所以x0,y0也没变。这样,就得到ax+by=c的通解为(x*(c/d)+k*(lcm/a),y*(c/d)-k*(lcm/b))

#include<stdio.h>
#include<stdlib.h>
void exgcd(__int64 a,__int64 b,__int64 &d,__int64 &x,__int64 &y)
{
	if (!b) d=a,x=1,y=0;
	else
	{
		exgcd(b,a%b,d,y,x);
		y-=a/b*x;
	}
	return;
}
int main()
{
	__int64 x,y,m,n,L;
	while(scanf("%I64d %I64d %I64d %I64d %I64d",&x,&y,&m,&n,&L)!=EOF)
	{
		x=x%L;
		y=y%L;
		__int64 a=n-m;
		__int64 b=L;
		__int64 c=x-y;
		if(a==0)
		{
			printf("Impossible\n");
			continue;
		}
		if(c<0)
		{
			c=-c;
			a=-a;
		}
		__int64 xx,yy,d;
		if(a>0)
		{
			exgcd(a,b,d,xx,yy);
			if(c%d!=0)
			{
				printf("Impossible\n");
				continue;
			}
			xx*=c/d;
			xx=xx%(b/d);
			if(xx<0)
				xx=b/d+xx;
			printf("%I64d\n",xx);
		
		}
		else
		{
			a=-a;
			exgcd(a,b,d,xx,yy);
			if(c%d!=0)
			{
				printf("Impossible\n");
				continue;
			}
			xx*=c/d;
			xx=xx%(b/d);
			if(xx>0)
				xx-=b/d;
			
			printf("%I64d\n",-xx);				
		
		}
	}
	//system("pause");
	return 0;
}

hdoj2588
题意:给出n、m,求1<=x<=n,且gcd(x,n)>=m的这样的x有多少个
思路来自网上。。悲剧,想不到啊,以下是自己的一些总结
假设k是n的约数且k>=m,并设b与n/k互质,那么b和n/k都乘上k之后,得到n与bk,他们的最大公约数是k>=m。这里用到的关键一点就是:如果a与b互质,那么a*t与b*t的最大公约数是t。
那么只要找出所有phi(n/k)就可以了。(k是>=m的n的约数),答案就是所有phi(n/k)之和。
一个问题:设b1是与n/k1互质的数,b2是与n/k2互质的数,是否可能b1k1、b2k2相等?如果可能的话,就会造成重复计算
答:其实是不可能的。因为b1与n/k1互质,所以b1k1与最大公约数为k1,同理:b2k2与最大公约数为k2
证:假设b1k1=b2k2。
(1) 如果b1=b2,因为k1、k2是n的不同的约数,所以b1k1!=b2k2。
(2) 如果b1!=b2。
假设k1>k2,那么显然b2k2的最大真约数是k1,而k1又是n的约约数,可见b2k2与n的最大公约数是k1,这与b2k2与n的最大公约数是k2矛盾。
k1

#include<stdio.h>
__int64 phi(__int64 n)
{
	__int64 ans = n;
	for(__int64 i = 2; i*i<= n; i++)
		if(n%i == 0)
		{
			ans = ans / i * (i-1);
			while(n%i == 0)
			{
				n /= i;
			}
		}
	if(n > 1)
		ans = ans / n *(n-1);
	return ans;
}
int main()
{
	int t,i,j;
	__int64 n,m;
	scanf("%d",&t);
	while(t–)
	{
		scanf("%I64d %I64d",&n,&m);
		if(m==1)
		{
			printf("%I64d\n",n);
			continue;
		
		}
		__int64 result=0;
		for(i=1;i*i<=n;i++)
		{
			if(n%i!=0) continue;
			if(i<m)
			{
				if(n/i>=m)
					result+=phi(i);
			}
			else if(i>=m)
			{
				result+=phi(n/i);
				if(n/i>=m && i*i!=n)
					result+=phi(i);
			
			}
		}
		
			
		printf("%I64d\n",result);


	}
	return 0;
}

hdoj1788
解模线性方程组

#include<stdio.h>
typedef __int64 ll;
void exgcd(ll a,ll b,ll &d,ll &x,ll &y)
{
	if (!b) d=a,x=1,y=0;
	else
	{
		exgcd(b,a%b,d,y,x);y-=a/b*x;
	}
	return;
}
int main()
{
	int n,i,aa;
	while(scanf("%d %d",&n,&aa)!=EOF && !(n==0 && aa==0))
	{
		ll a1,r1,a2,r2;
		scanf("%I64d",&a1);
		r1=a1-aa;
		for(i=2;i<=n;i++)
		{
			scanf("%I64d",&a2);
			r2=a2-aa;
			ll a=a1,b=a2,c=r2-r1;
			ll d,x,y;
			exgcd(a,b,d,x,y);
			ll t=b/d;
			x=((x*c/d)%t+t)%t;
			r1=a1*x+r1;
			a1=a1/d*a2;
		}
		printf("%I64d\n",r1);
	}
	return 0;
}

hdoj1299
题意:对于1/x+1/y=1/n。(1<=x<=y,x、y为整数,n已知)。求满足方程的x、y有多少对。
尼玛。。。想不出来,看了别人思路。。罪过。。
思路:显然x>=n,y>=n。那么可以假设y=x+k。代入方程得到x=n+((n^2)/k)。那么显然必须(n^2)/k是整数。
则k必然是(n^2)的因子。解的个数其实就是k的个数。而且因为x<=y,所以k>=n,k的个数就是n^2的因子数,但是n^2可能达到2^18,很大。其实只要对n分解素因素即可,假设n分解后为n=p1^k1+p2^k2+……+pm^km.那么n的因子个数为(k1+1)(k2+1)……(km+1)。而n^2的因子个数很显然是(2*k1+1)(2*k2+1)……(2*km+1).那么满足k>=n的k的可能个数就是(ans+1)/2(为什么呢?因为因子是对称的嘛。。对于n^2来说,有一个小于n的因子k,必有一个大于n的因子(n^2)/k)

#include<stdio.h>
#include<string.h>
typedef __int64 ll;
const int N=1000000;
ll pr[N+10],p[(N+10)/10],lp;
void gp()
{
	for(ll i=2;i<=N;i++)
	{
		if(!pr[i]) p[++lp]=pr[i]=i;
		for(int j=1;j<=lp && i*p[j]<=N;j++)
		{
			pr[i*p[j]]=p[j];
			if(i%p[j]==0) break;
		}
	}
	return;
}
ll b[30],k[30];
int cnt;
void gn(ll n)
{
	int i;
	ll t;
	cnt=0;
	memset(k,0,sizeof(k));
	while(n>1)
	{
		if(n<=N)
		{
			t=pr[n];
		}
		else
		{
			t=n;
			for(i=1;i<=lp && p[i]<=n/p[i];i++)
				if(n%p[i]==0)
				{
					t=p[i];
					break;
				}
		}
		b[++cnt]=t;
		while(n%t==0)
		{
			n/=t;
			k[cnt]++;
		}
	}
	return;
}
int main()
{
	int t,cases=0;
	int i;
	gp();
	scanf("%d",&t);
	while(t--)
	{
		ll n;
		ll ans=1;
		scanf("%I64d",&n);
		gn(n);
		for(i=1;i<=cnt;i++)
			ans*=(2*k[i]+1);
		ans=(ans+1)/2;
		printf("Scenario #%d:\n%I64d\n\n",++cases,ans);
		
	}
	return 0;
}

hdoj1695
题意:给你两个区间[1,a],[1,b],问你两个区间各选一个整数x,y,gcd(x,y)=k的有多少对(无序对).
思路:gcd(x,y)=d,说明x/d、y/d互质。因为是无序的,所以先给定次序x<=y,问题转化为[1,a/d][1,b/d]两个区间各选x、y,满足x、y互质的对数有多少。设b=a/d,d=b/d,假设b是小区间,那么:
对于<=b的y,显然结果就是[1,b]每个数的欧拉函数值之和。
对于>b的y,要找到与y互质的且<=b的x有多少,这时欧拉函数失效了。可以用容斥求出[1,b]区间与y不互质的数有多少,然后b减去不互质的数的数量就是与y互质且<=b的x的数量。当然先要对y分解素因素。因为y<=10^5,所以可以预处理素数,log时间分解素因素。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef __int64 ll;
const int N=100000;
ll pr[N+10],p[N+10];
ll phi[N+10];
int cnt,lp;
void gp(){
	for(int i=2;i<=N;i++)
	{
		if(!pr[i]) p[++lp]=pr[i]=i;
		for(int j=1;j<=lp && i*p[j]<=N;j++)
		{
			pr[i*p[j]]=p[j];
			if(i%p[j]==0) break;
		}
	}
	return;
}
void oula()
{
	int i,j;
	for(i=1;i<=N;i++)
		phi[i]=i;
	for(i=1;i<=lp;i++)
	{
		for(j=p[i];j<=N;j+=p[i])
		{
			phi[j]=phi[j]/p[i]*(p[i]-1);
		}
	}
	return;
}
ll pi[30],ki[30];
void fenjie(int n)
{
	cnt=0;
	memset(ki,0,sizeof(ki));
	while(n!=1)
	{
		ll t=pr[n];
		pi[++cnt]=t;
		ki[cnt]=0;
		while(n%t==0)
		{
			n/=t;
			ki[cnt]++;
		}
	}
	return;
}
ll sum[N+10];
ll ans;
void dfs(int flag,int x,ll p,ll a)
{
	if(flag&1)
		ans+=a/p;
	else
		ans-=a/p;
	for(int i=x+1;i<=cnt;i++)
		dfs(flag+1,i,p*pi[i],a);
	return;
}
int main()
{
	int i,j;
	int t,cases=0;
	ll a,b,c,d,k;
	gp();
	oula();
	sum[1]=phi[1];
	for(i=2;i<=N;i++)
		sum[i]=sum[i-1]+phi[i];
	scanf("%d",&t);
	while(t--)
	{
		scanf("%I64d %I64d %I64d %I64d %I64d",&a,&b,&c,&d,&k);
		if(k==0 || (k>b && k>d))
		{
			printf("Case %d: 0\n",++cases);
			continue;
		}
		a=b/k;b=d/k;
		if(a>b){a=a^b;b=a^b;a=a^b;}
		if(a==b)
		{
			printf("Case %d: %I64d\n",++cases,sum[b]);
			continue;
		}
		ll result=sum[a];
		for(i=a+1;i<=b;i++)
		{
			fenjie(i);
			ans=0;
			for(j=1;j<=cnt;j++)
				dfs(1,j,pi[j],a);
			ans=a-ans;
			result+=ans;
		}
		printf("Case %d: %I64d\n",++cases,result);
	}
	return 0;
}

Codeforces 264B (Good Sequences)
题意:给你序列a1,a2,a3,……,an。n<=10^5,1<=ai<=10^5,严格升序给出。要你求出任意相邻数不互质的严格升序子序列最大长度。
O(n^2)的dp是很好想到的,方程:dp[i]=max{dp[j]|1<=j 需要换一种dp的形式。可以用dp[i]表示以序列中含素因子i的最后一个数结尾的子序列最大长度,显然:每次读入一个数,他都可以加在含它的素因子的数结尾的子序列后面,所以每次读入a[i]的时候,只需找出含它的素因子的数结尾的最长长度,并在这个长度上+1根新他的素因子即可

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef __int64 ll;
const int N=100000;
int pr[N+10],p[N+10];
int cnt,lp;
int max(int a,int b)
{
	return a>b?a:b;
}
void gp(){
	for(int i=2;i<=N;i++)
	{
		if(!pr[i]) p[++lp]=pr[i]=i;
		for(int j=1;j<=lp && i*p[j]<=N;j++)
		{
			pr[i*p[j]]=p[j];
			if(i%p[j]==0) break;
		}
	}
	return;
}
void fenjie(int n,int *pp)
{
	cnt=0;
	while(n!=1)
	{
		int t=pr[n];
		pp[++cnt]=t;
		while(n%t==0)
			n/=t;
	}
	pp[0]=cnt;
	return;
}
int a[N+10],dp[N+10];
int pp[N+10][30];
int main()
{
	int i,j;
	int n;
	gp();
	for(i=2;i<=N;i++)
		fenjie(i,pp[i]);
	pp[1][0]=0;
	while(scanf("%d",&n)!=EOF)
	{
		if(n==1)
		{
			scanf("%d",&a[1]);
			printf("1\n");
			continue;
		}
		memset(dp,0,sizeof(dp));
		for(i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			if(a[i]==1)
				continue;
			int tmp=-1;
			for(j=1;j<=pp[a[i]][0];j++)
			{
				tmp=max(tmp,dp[pp[a[i]][j]]);
			}
			for(j=1;j<=pp[a[i]][0];j++)
			{
				dp[pp[a[i]][j]]=tmp+1;
			}
		}
		int max=-1;
		for(i=2;i<=N;i++)
			if(dp[i]>max)
				max=dp[i];
		printf("%d\n",max);
	}


	return 0;
}

hdoj4483
好难,还没理清楚。。
先放上pick定理:pick定理:在一个平面直角坐标系内,以整点为顶点的简单多边形(任两边不交叉),它内部整点数为a,它的边上(包括顶点)的整点数为b,则它的面积S = a+b/2-1
pick定理及其证明
一个结论:对于长a,宽b的整点矩形,它的一条对角线上的整点数为gcd(a,b)-1

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>