SGU 112:a^b-b^a

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=112

题目大意:

      输入a,b输出a^b-b^a的值。(1<=a,b<=100)

解题思路:

      肯定是用高精度算法,可是比较懒阿,先用JAVA写一个,然后C++的以后写吧。

解题代码:

import java.math.*;
import java.io.*;
import java.util.*;
public class Solution{
    public static void main(String[] args){
        Scanner cin=new Scanner(System.in);
        int  a,b;
        while(cin.hasNext()){
            a=cin.nextInt();
            b=cin.nextInt();
            System.out.println(BigInteger.valueOf(a).pow(b).subtract(BigInteger.valueOf(b).pow(a)));
        }
    }
}

扩展知识:http://blog.csdn.net/soberman/archive/2009/03/10/3978074.aspx

SGU 113: Nearly prime numbers

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=113

题目大意:

      如果一个数可以分解成2个素数的乘积,那么就输出yes否则输出no.

解题思路:

      先筛选出素数,然后判断找到那个能整除这个数的素数,判断商是否为素数就行啦!起先题目给看错了以为是相邻的素数的积。

解题代码:

#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
#define Max 50000
bool isprime[Max];
int prime[Max];
int cp;
void mkprime(){
	cp=1;
	memset(isprime,true,Max);
	prime[0]=2;
	for(int i=2;i<Max;i++){
		if(isprime[i]==true){
			prime[cp++]=i;
			for(int j=1;i*j<Max;j++)
				isprime[i*j]=false;
		}
	}
}
bool isp(int n){
	if(n==1) return false;
	if(((n!=2)&&!(n%2))||((n!=3)&&!(n%3))||
	   ((n!=5)&&!(n%5))||((n!=7)&&!(n%7)))
			return false;
	int t=sqrt(n);
	for(int i=2;i<t;i++)
		if(n%i==0)
			return false;
	return true;
}
int main(){
	mkprime();
	int cas;
	cin>>cas;
	while(cas--){
		int n;
		cin>>n;
		int flag=0;
		for(int i=0;i<cp;i++){
			if(n%prime[i]==0)
				if(isp(n/prime[i])){
						flag=1;
						break;
				}
		}
		if(flag)
			cout<<"Yes"<<endl;
		else
			cout<<"No"<<endl;
	}
	return 0;
}

扩展知识:http://en.wikipedia.org/wiki/Primality_test

SGU 102: Coprimes

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=102

题目大意:

     求不大于N且与N互质的数的个数。

解题思路:

      刚开始就想到暴力法,枚举每个数看看是不是gcd(n,i)==1。

      后来想到了欧拉函数,这不就是典型的欧拉函数题,先分解素数然后求欧拉函数。

      欧拉函数法用的时间是暴力法的一半。

解题代码:

#include<iostream>
using namespace std;
int gcd(int a,int b){
	return b?gcd(b,a%b):a;
}
int main(){
	int n;
	while(cin>>n){
		int sum=0;
		for(int i=1;i<=n;i++){
			if(gcd(n,i)==1)
				sum++;
		}
		cout<<sum<<endl;
	}
}
#include<iostream>
#include<cstring>
using namespace std;
#define Max 10000
bool isprime[Max+10];
int  prime[Max+10];
int  countp;
void mkprime(int n){
	countp=1;
	memset(isprime,true,Max+10);
	prime[0]=2;
	for(int i=3;i<=n;i+=2){
		if(isprime[i]==true){
			prime[countp++]=i;
			for(int j=1;i*j<=n;j++)
				isprime[i*j]=false;
		}
	}
}
int eular(int n){
	for(int i=0;prime[i]<=n&&i<countp;i++)
		if(n%prime[i]==0){
			n/=prime[i];
			n*=prime[i]-1;
		}
	return n;
}
int main(){
	int n;
	while(cin>>n){
		mkprime(n);
		if(n==1)
			cout<<1<<endl;
		else
			cout<<eular(n)<<endl;
	}
}

 扩展知识:

http://en.wikipedia.org/wiki/Euler%27s_totient_function

http://linuxsir.org/bbs/showthread.php?t=278294

UVA 369: Combinations

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=5&problem=305&mosmsg=Submission+received+with+ID+8692218

题目大意:

GIVEN:

displaymath41

 

Compute the EXACT value of:

 

displaymath43

给你N和M求C。

解题思路:

      由于直接求出阶乘数据庞大,要用高精度算法。但是据题目说答案不超过32位,所以就用新的方法来做。把公式转化为

 

$$C=\frac{(M+1)*...*N}{(N-M)!}$$

然后把m+1到n都存入数组,用(n-m)到1去和数组的数一起除以它们的最大公约数。最后把数组里面的数相乘起来就是答案。

解题代码:

#include<iostream>
using namespace std;
typedef long long ll;
ll s[105];
ll gcd(ll a,ll b){
	return a%b==0?b:gcd(b,a%b);
}
int main(){
	ll n,m;
	while(cin>>n>>m&&m+n){
		for(int i=1;i<=n;i++)
			s[i]=i;
		ll t=n-m,sum=1;
		if(t!=0){
			while(t!=1){
				for(int i=m+1,j=t;i<=n&&j!=1;i++){
					ll g=gcd(s[i],j);
					s[i]/=g;
					j/=g;
				}
				t--;
			}
			for(int i=m+1;i<=n;i++)
				sum*=s[i];
		}
		cout<<n<<" things taken "<<m<<" at a time is "<<sum<<" exactly."<<endl;
	}
        return 0;
}

扩展知识:http://en.wikipedia.org/wiki/Combinatorics

UVA 575: Skew Binary

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=7&problem=516&mosmsg=Submission+received+with+ID+8687739

题目大意:

      定义一个新的进制数,把这种新数转化为十进制数。

解题代码:

#include<iostream>
using namespace std;
int main(){
	string s;
	while(cin>>s&&s!="0"){
		int sum=0;
		int len=s.length();
		for(int i=0;i<len;i++)
				sum+=(s[i]-'0')*((1<<(len-i))-1);
		cout<<sum<<endl;
	}
}

扩展知识:http://en.wikipedia.org/wiki/Positional_notation