a题是比较经典的扩展欧几里得习题,单独放在一篇博客里讲解。
B - 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
思路:设A=B*X。n=A-(A/mod)*mod,所以n=B*X-(A/mod)*mod。设(A/mod)=Y。所以原式等于:n=B*X-Y*mod。因为gcd(B,mod)=1,所以B*x-mod*y=1,方程两边同时乘于n,得到B*n*x-mod*y*n=n.所以X=n*x,其中X为B关于mod的逆元。然后就用扩展欧几里得解就可以了。
#include<algorithm>
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
const int mod=9973;
ll x,y;
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 z=x;x=y;y=z-y*(a/b);
//return d;
}
int main(){
int t;
scanf("%d",&t);
ll n,b,x,y,ans;
while(t--){
scanf("%lld%lld",&n,&b);
exgcd(b,mod,x,y);
x=x*n;
ll ans=(x%mod+mod)%mod;
printf("%lld\n",ans);
}
return 0;
}
C - 乘法逆元
给出2个数M和N(M < N),且M与N互质,找出一个数K满足0 < K < N且K * M % N = 1,如果有多个满足条件的,输出最小的。
Input
输入2个数M, N中间用空格分隔(1 <= M < N <= 10^9)
Output
输出一个数K,满足0 < K < N且K * M % N = 1,如果有多个满足条件的,输出最小的。
Sample Input
2 3
扩展欧几里得打表就可以了。注意如果k<0,要处理一下。
#include<algorithm>
#include<cstdio>
#include<iostream>
using namespace std;
const int MAXN=1000005;
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 z=x;x=y;y=z-y*(a/b);
//return d;
}
int main(){
ll m,n;
ll x,y;
while(~scanf("%lld%lld",&m,&n)){
exgcd(m,n,x,y);
int k=(x%n+n)%n;
printf("%lld\n",k);
}
return 0;
}
Sample Output
2
D - 3的幂的和
求:3^0 + 3^1 +...+ 3^(N) mod 1000000007
Input
输入一个数N(0 <= N <= 10^9)
Output
输出:计算结果
Sample Input
3
Sample Output
40
题目大致思路:用等比数列前n项和公式可得((3^n+1-1)/2)mod,然后在由费马小定理求2关于mod的逆元。
#include<algorithm>
#include<cstdio>
#include<iostream>
#define mod 1000000007
using namespace std;
typedef long long ll;
ll poww(ll x,ll n){
ll res=1;
while(n>0){
if(n&1) res=res*x%mod;
x=x*x%mod;
n>>=1;
}
return res;
}
int main(){
int n;
while(~scanf("%d",&n)){
ll x=(poww(3,n+1)-1)%mod;
ll y=(poww(2,mod-2)%mod);//费马小定理计算2的乘法逆元
ll ans=(x*y)%mod;
printf("%lld\n",ans);
}
}
E - Integer Divisibility
If an integer is not divisible by 2 or 5, some multiple of that number in decimal notation is a sequence of only a digit. Now you are given the number and the only allowable digit, you should report the number of digits of such multiple.
For example you have to find a multiple of 3 which contains only 1's. Then the result is 3 because is 111 (3-digit) divisible by 3. Similarly if you are finding some multiple of 7 which contains only 3's then, the result is 6, because 333333 is divisible by 7.
Input
Input starts with an integer T (≤ 300), denoting the number of test cases.
Each case will contain two integers n (0 < n ≤ 106 and n will not be divisible by 2 or 5) and the allowable digit (1 ≤ digit ≤ 9).
Output
For each case, print the case number and the number of digits of such multiple. If several solutions are there; report the minimum one.
Sample Input
3
3 1
7 3
9901 1
Sample Output
Case 1: 3
Case 2: 6
Case 3: 12
题目思路:大数取模,直接上板子就可以了,注意开到long long。
#include<algorithm>
#include<cstdio>
#include<string>
#include<iostream>
using namespace std;
int main(){
int t;
scanf("%d",&t);
long long kase=0,a,b;
while(t--){
scanf("%lld%lld",&a,&b);
long long ans=b,cnt=1;
while(ans%a!=0){
ans=(ans*10+b)%a;
cnt++;
}
printf("Case %lld: %lld\n",++kase,cnt);
}
return 0;
}
F - Large Division
Given two integers, a and b, you should check whether a is divisible by b or not. We know that an integer a is divisible by an integer b if and only if there exists an integer c such that a = b * c.
Input
Input starts with an integer T (≤ 525), denoting the number of test cases.
Each case starts with a line containing two integers a (-10200 ≤ a ≤ 10200) and b (|b| > 0, b fits into a 32 bit signed integer). Numbers will not contain leading zeroes.
Output
For each case, print the case number first. Then print 'divisible' if a is divisible by b. Otherwise print 'not divisible'.
Sample Input
6
101 101
0 67
-101 101
7678123668327637674887634 101
11010000000000000000 256
-202202202202000202202202 -101
Sample Output
Case 1: divisible
Case 2: divisible
Case 3: divisible
Case 4: not divisible
Case 5: divisible
Case 6: divisible
题目思路:在为负数的时候特判一下,然后直接上板子。
#include<algorithm>
#include<cstdio>
#include<string>
#include<iostream>
using namespace std;
string a;
long long b;
int main(){
int t;
scanf("%d",&t);
int kase=0;
while(t--){
cin>>a>>b;
long long len=a.length();
long long ans=0;
long long i=0;
if(a[0]=='-') i++;
for(;i<len;i++){
ans=(ans*10+a[i]-'0')%b;
}
if(ans==0) printf("Case %d: divisible\n",++kase);
else printf("Case %d: not divisible\n",++kase);
}
return 0;
}