1. 程式人生 > >練習9(數論初步)

練習9(數論初步)

A - 整除的尾數


一個整數,只知道前幾位,不知道末二位,被另一個整數除盡了,那麼該數的末二位該是什麼呢? Input輸入資料有若干組,每組資料包含二個整數a,b(0<a<10000, 10<b<100),若遇到0 0則處理結束。 Output對應每組資料,將滿足條件的所有尾數在一行內輸出,格式見樣本輸出。同組資料的輸出,其每個尾數之間空一格,行末沒有空格。 Sample Input
200 40
1992 95
0 0
Sample Output
00 40 80
15

	#include<iostream>

	using namespace std;
	void print(int i){
		if(i<10) cout<<0;
		cout<<i;
	}
	int main(){
		int a,b;
		while(cin>>a>>b){
			if(a==0&&b==0) break;
			bool tag=false;
			for(int i=0;i<100;i++){
				int t=a*100+i;
				if(t%b==0){
					if(!tag)
						tag=true;
					else 
						cout<<" ";
					print(i);
				}
			}
			cout<<endl;
		}
	}

 

B - Number Sequence

  A number sequence is defined as follows: 

f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7. 

Given A, B, and n, you are to calculate the value of f(n). 
InputThe input consists of multiple test cases. Each test case contains 3 integers A, B and n on a single line (1 <= A, B <= 1000, 1 <= n <= 100,000,000). Three zeros signal the end of input and this test case is not to be processed. 
OutputFor each test case, print the value of f(n) on a single line. 
Sample Input
1 1 3
1 2 10
0 0 0
Sample Output
2
5

明顯週期數列 方法1: 推到週期
#include<iostream>

using namespace std;
/*
1 1 16
1 2 18
1 3 24
1 4 48
2 1 12
2 2 48
*/
int f[100];
 int main(){
	int a,b,n;
	while(cin>>a>>b>>n,a||b||n){
	//if(a==0&&b==0&&n==0) break;
//	cout<<"i "<<1<<" "<<f[1]<<endl;
//	cout<<"i "<<2<<" "<<f[2]<<endl;
	int i;
	f[1]=1;f[2]=1;
//	f[3]=(a*f[1]+b*f[2])%7;
	for(i=3;i<100;i++){
		f[i]=(a*f[i-1]+b*f[i-2])%7;
//		cout<<i<<" "<<f[i]<<endl;
		if(f[i]==1&&f[i-1]==1) {
			break;
		}
	}
	//cout<<time<<endl;
	f[0]=f[i-2];
	n=n%(i-2);
//	for(int j=0;j<time;j++)
//		cout<<f[j]<<endl;
	cout<<f[n]<<endl;
	}
	return 0;
}
方法2: 知道週期, 不推,用一個比較大的數(週期倍數)
#include<iostream>

using namespace std;
 
int f[1009];
 int main(){
	int a,b,n;
	while(cin>>a>>b>>n,a||b||n){
	//if(a==0&&b==0&&n==0) break;
	int i;
	f[1]=1;f[2]=1;
	for(i=3;i<=1008;i++){
		f[i]=(a*f[i-1]+b*f[i-2])%7;
	}
	cout<<f[(n-1)%1008+1]<<endl;
	}
	return 0;
}

方法3: 矩陣快速冪

C - Factorial

  The most important part of a GSM network is so called Base Transceiver Station (BTS). These transceivers form the areas called cells (this term gave the name to the cellular phone) and every phone connects to the BTS with the strongest signal (in a little simplified view). Of course, BTSes need some attention and technicians need to check their function periodically. 
ACM technicians faced a very interesting problem recently. Given a set of BTSes to visit, they needed to find the shortest path to visit all of the given points and return back to the central company building. Programmers have spent several months studying this problem but with no results. They were unable to find the solution fast enough. After a long time, one of the programmers found this problem in a conference article. Unfortunately, he found that the problem is so called "Travelling Salesman Problem" and it is very hard to solve. If we have N BTSes to be visited, we can visit them in any order, giving us N! possibilities to examine. The function expressing that number is called factorial and can be computed as a product 1.2.3.4....N. The number is very high even for a relatively small N. 

The programmers understood they had no chance to solve the problem. But because they have already received the research grant from the government, they needed to continue with their studies and produce at least some results. So they started to study behaviour of the factorial function. 

For example, they defined the function Z. For any positive integer N, Z(N) is the number of zeros at the end of the decimal form of number N!. They noticed that this function never decreases. If we have two numbers N1<N2, then Z(N1) <= Z(N2). It is because we can never "lose" any trailing zero by multiplying by any positive number. We can only get new and new zeros. The function Z is very interesting, so we need a computer program that can determine its value efficiently. 
InputThere is a single positive integer T on the first line of input. It stands for the number of numbers to follow. Then there is T lines, each containing exactly one positive integer number N, 1 <= N <= 1000000000. 
OutputFor every number N, output a single line containing the single non-negative integer Z(N). 
Sample Input
6
3
60
100
1024
23456
8735373
Sample Output
0
14
24
253
5861
2183837



思路:n! 後面產生0 ,只有2*5  2的個數明顯大於5的個數,只需求出能分解出多少個5 計算5的個數的方法
#include<iostream>
#include<cstdio>
using namespace std;


int main(){
	int T;
	cin>>T;
	while(T--){
		int n;
		scanf("%d",&n);
		__int64 ans=0;
		while(n){
			n/=5;
			ans+=n;
		}
		printf("%I64d\n",ans);
	}
}

D - Least Common Multiple

  The least common multiple (LCM) of a set of positive integers is the smallest positive integer which is divisible by all the numbers in the set. For example, the LCM of 5, 7 and 15 is 105. 

InputInput will consist of multiple problem instances. The first line of the input will contain a single integer indicating the number of problem instances. Each instance will consist of a single line of the form m n1 n2 n3 ... nm where m is the number of integers in the set and n1 ... nm are the integers. All integers will be positive and lie within the range of a 32-bit integer. 
OutputFor each problem instance, output a single line containing the corresponding LCM. All results will lie in the range of a 32-bit integer. 
Sample Input
2
3 5 7 15
6 4 10296 936 1287 792 1
Sample Output
105
10296
#include<iostream>

using namespace std;

int n,m;
int *arr;

int gcd(int a,int b){
	return b!=0?gcd(b,a%b):a;
}

int lcm(int a,int b){
	return a/gcd(a,b)*b;//防止溢位
}

int main(){
	while(cin>>n){
		while(n--){
			cin>>m;
			arr=new int[m];
			cin>>arr[0];
			int ans=arr[0];
			for(int i=1;i<m;i++){
				cin>>arr[i];
				ans=lcm(ans,arr[i]);
			}
			cout<<ans<<endl;
		}
	}
	return 0;
}


求解最小公倍數和最大公約數的方法。。。
H - Romantic
The Sky is Sprite. 
The Birds is Fly in the Sky. 
The Wind is Wonderful. 
Blew Throw the Trees 
Trees are Shaking, Leaves are Falling. 
Lovers Walk passing, and so are You. 
................................Write in English class by yifenfei 

 

Girls are clever and bright. In HDU every girl like math. Every girl like to solve math problem! 
Now tell you two nonnegative integer a and b. Find the nonnegative integer X and integer Y to satisfy X*a + Y*b = 1. If no such answer print "sorry" instead. 
InputThe input contains multiple test cases. 
Each case two nonnegative integer a,b (0<a, b<=2^31) 
Outputoutput nonnegative integer X and integer Y, if there are more answers than the X smaller one will be choosed. If no answer put "sorry" instead. 
Sample Input
77 51
10 44
34 79
Sample Output
2 -3
sorry
7 -3
拓展歐幾里得演算法解不定方程的方法注意調解的過程若x,y為a*x+b*y=d的一個解則 a*(x+b)+b*(y-a)=d x=x+b,y=y-a的一個解拓展歐幾里得: 對於a'=b,b'=a%b 而言,我們求得 x, y使得 a'x+b'y=Gcd(a',b') 由於b'=a%b=a-a/b*b (注:這裡的/是 程式設計語言中的 除法) 那麼可以得到: a'x+b'y=Gcd(a',b') ===> bx+(a - a / b * b)y = Gcd(a', b') = Gcd(a, b) ===> ay +b(x - a / b*y) = Gcd(a, b) 因此對於a和b而言,他們的相對應的p,q分別是 y和(x-a/b*y) 使用擴充套件歐幾里德演算法解決不定方程的辦法 對於不定整數方程pa+qb=c,若 c mod Gcd(a, b)=0,則該方程存在整數解,否則不存在整數解。 有種較為不嚴謹的方法證明,不過至少彌補了一點空白,望某些數論大師補充修改: 由於我們知道,存在一組x與y使得a*x+b*y=gcd(a,b)。 將等式兩邊同時乘以 整數k,即a*x*k+b*y*k=gcd(a,b)*k。如果c mod gcd(a,b)=f,則0<=f<gcd(a,b)。 那麼可以令c=gcd(a,b)*k+f。這樣一來,就有a*x*k+b*y*k+f=c。 若f     0,由於f<gcd(a,b)<=a<=b(假設a<=b),所以不存在f=a*m(m為整數),也就不存在a*(x*k+m)+b*y*k=c。也就是說,不存在a*x+b*y=c的整數解x與y。 所以f=0,即只有當c mod gcd(a,b)=0時,a*x+b*y=c有正整數解。得證。
#include<iostream>
#include<cstdio>
//typedef __int64 ll;

using namespace std;


int gcd(int a,int b,int& x,int& y){
	if(b==0){
		x=1;
		y=0;
		return a;
	}
	int d=gcd(b,a%b,y,x);
	y-=a/b*x;
	return d;
}

int main(){
	ios_base::sync_with_stdio(false);
	int a,b;
	while(cin>>a>>b){
		int x,y;
		int d=gcd(a,b,x,y);
		if(d==1){
			while(x<0){
				x+=b;
				y-=a;
			}
			cout<<x<<" "<<y<<endl;