7.24 练习

HDU 1576  A/B  逆元

要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1)。

Input

数据的第一行是一个T,表示有T组数据。
每组数据有两个数n(0 <= n < 9973)和B(1 <= B <= 10^9)。

Output

对应每组数据输出(A/B)%9973。

Sample Input

2
1000 53
87 123456789

Sample Output

7922
6060

令k=9973,显然k为素数。
令A=m*B;题目中 所求的 是m;
由题目已知:
(B,k)=1
B≡1 mod k;
m*B≡n mod k;
由同余定理可得:
n*(m/n)*B≡n mod k;
(m/n)*B≡1 mod k/(k,n);
因为 k为素数 所以 (k,n)=1;
即 (m/n)*B≡1 mod k;
所以 m/n 为B模k的逆;
令 x=m/n;
表达式 (m/n)*B≡1 mod k;可写成B*x+k*y=1;
根据exgcd 可算出 x;
注意 x的通解 为 x0+k/(B,k)*t;t=0,-1,1,2,-2,.......
算出结果 若x<0;x+=k;去正数。

#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
void exgcd(ll a, ll b, ll &x, ll &y)
{
    if (b == 0)
    {
        x = 1, y = 0;
        return ;
    }
    exgcd(b, a%b, x, y);
    ll temp = x;
    x = y;
    y = temp - (a / b)*y;
}
int main()
{
    ll T;cin>>T;
    while(T--)
    {
        ll n,B,x,y;
        cin>>n>>B;
        exgcd(B,9973,x,y);
        if(x<0)x+=9973;
        ll ans;
        ans=n*x%9973;
        cout<<ans<<endl;
    }
}

---------------

由于gcd(b,9973)=bx1+9973y1=1所以可得一组(x1,y1)

然后求(a/b)%9973,a/b=x,所以a=bx,有n=a%9973=a-a/9973*9973=bx-9973y;

费马小引理求逆 AC code:
#include <iostream>
#include<stdio.h>
using namespace std;
typedef long long LL;
const LL mod=9973;
LL powmod(LL a,LL b){
    LL ans=1;
    a=a%mod;
    while(b){
         if(b&1)   ans=ans*a%mod;
         a=a*a%mod;
         b>>=1;
    }
    return ans;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
	{
        int n,b;
        cin>>n>>b;
        LL inv=powmod(b,mod-2);//inv 是b的逆元
        cout<<n*inv%mod<<endl;
    }
    return 0;
}

  51NOD 1256

解题思路:K*M%N=1等价于K*M=1+N*X等价于K*M-X*N=1,这种形式就是不定方程x*m+y*n=gcd(m,n)的形式,这里m和n给出来了,且互质
,所以gcd(m,n)=1,然后用exgcd求解不定方程即可。
扩展欧几里得算法
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
ll exgcd(ll a,ll b,ll &x,ll &y)
{
 if(!b)
 {
  x=1;
  y=0;
  return a;
 }
 ll  r=exgcd(b,a%b,x,y);
 ll  t=x;
 x=y;
 y=t-(a/b)*y;
 return r;
} 
int main()
{
 ll  m,n,x,y;
 while(cin>>m>>n)
	{
		int c=exgcd(m,n,x,y);//最大公约数
		while(x<0)//所求出来的解可能是负的,题目说要最小的正数解,这样循环把他弄成正数
		{
			x=x+n;
		}
	 	cout<<x<<endl;
	}
 return 0;
}

51NOD 1013

#include<stdio.h>
#define mod 1000000007
#include<iostream>
using namespace std;
typedef long long ll;
ll PowerMod(ll a, ll b, ll c)        //快速幂取余
{
    ll ans = 1;
    a = a % c;             //预处理,防止出现a比c大的情况
    while(b > 0)
    {
	    if(b&1)
	    {
		    ans = (ans *a )% c;
	    }
	    b >>= 1;
	    a = (a * a) % c;
    }
return ans;
}

int main()
{
	int n;
	cin>>n;
	cout<<(PowerMod(3,n+1,mod)-1)*500000004 % mod; 
	return 0;
}

E题

Time Limit Exceeded:
#include<iostream>
using namespace std;
int main()
{
    long long i=1,t,n,d;
    cin>>t;
    while(t--)
    {
        cin>>n>>d;
        long long ans=1,r=d;
        while(r%n)
        {
            r=r*10+d;
            ans++;
        }
        cout<<"Case " <<i++<<": "<<ans<<endl;
    }
    return 0;
 }


 AC :
#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
    long long i=1,t,n,d;
    cin>>t;
    while(t--)
    {
        cin>>n>>d;
        long long ans=1,r=d;
   while(r%n)
        {
            r=r%n*10+d;//r:下一个被除数
            ans++;
        }
        cout<<"Case " <<i++<<": "<<ans<<endl;
    }
    return 0;
 }

猜你喜欢

转载自blog.csdn.net/tingtingyuan/article/details/81188559
今日推荐