SGU 119 数论

还是没有想到简单的方法,具体咋样自己百度吧。。。。方法搞得麻烦,快把自己整吐了,好在最后AC了。。。。。。T__T

首先是特殊情况,分别是a=0或b=0时,这个省略了

接下来:根据题意,(A0x +B0y) % n =0 转换为 A0x+ B0y = nk,首先判断 n 是否整除g=gcd(a0,b0),如果不整除,则该方程无解,令n1 = n*g/gcd(n,g)。如果n整除g,则n1 =g

然后得:x = (n1*k -b0*y)/a0,并求出方程的一个特解y0,则y =k( y0 + m*d) , d =a0/g,m为任意数

把x,y带入Ax + By = (1/a0)*[(a*n1+(a0*b-a*b0)*y0) k + (a0*b-a*b0)*a0/g],并令t = a0*b-b0*a;

接下来,枚举T,再枚举A和B。。。。。。附代码:

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>

#define ll __int64
#define N 10003
#define pb push_back

using namespace std;

vector<ll>res[N];

ll a0,b0,n,g,sum;

void extend(ll a,ll b,ll &x,ll &y)    
{    
    if (!b)    
    {    
        x=1;y=0;    
    }    
    else    
    {    
        extend(b,a%b,x,y);    
        ll temp=x;x=y;    
        y=temp-a/b*y;    
    }    
}    

void deal(ll y0,ll t,ll n1)
{
    ll x1,y1,d,a,b;
    extend(b0,a0,x1,y1);
    y1=y1*t/g;
    d=b0/g;
    y1=(y1%d+d)%d;
    for (b=y1;b<n;b+=d)
    {
        a=(a0*b-t)/b0;
        ll f = a*n1+t*y0;
        if (f%(n*a0)!=0) continue;
        if (a>=0&&a<n)
        {
            sum++;
            res[a].pb(b);
        }
    }   
}

ll gcd(ll a,ll b)
{
    if (a<b) return gcd(b,a);
    if (!b) return a;
    else return gcd(b,a%b);
}

void special()
{
    int i;
    if (!a0&&!b0)
    {
        cout<<1<<endl;
        cout<<0<<" "<<0<<endl;
    }
    else if (a0)
    {
        cout<<(n-1)/a0+1<<endl;
        for (i=0;i<n;i+=a0) cout<<i<<" "<<0<<endl;
    }
    else
    {
        cout<<(n-1)/b0+1<<endl;
        for (i=0;i<n;i+=b0) cout<<0<<" "<<i<<endl;
    }
}

int main()
{
    ll x1,y1,i,d,t,n1;
    cin>>n;
    cin>>a0>>b0;
    if (!a0||!b0) 
    {
        special();
        //system("pause");
        return 0;
    }
    g=gcd(a0,b0);
    ll y0,p,q;
    if (n%g!=0) n1=n*g/gcd(n,g);
    else n1=n;
    extend(a0,b0,x1,y1);
    y0=y1*n1/g;
    p=-b0/g;
    q=a0/g;
    for (i=p;i<=q;i++)
    {
        t=i*n*g;
        deal(y0,t,n1);
    }
    cout<<sum<<endl;
    for (i=0;i<n;i++)
        if (res[i].size())
        {
            sort(res[i].begin(),res[i].end());
            for (int j=0;j<res[i].size();j++) cout<<i<<" "<<res[i][j]<<endl;
        }
  //  system("pause");
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值