暑假专题test03

B题:http://poj.org/problem?id=2429

题解:有点复杂,要用模板,已跳;

C题:http://poj.org/problem?id=1930

ps:此题是一道小数化分数的题,循环小数有多少位,分母就有多少个9,不循环的小数有多少位,就在9后补多少个0,至于为什么这样,题主很Low,不太懂,对于我这种小白,我就理解为九分之几,则几循环,故多少九,按多少循环数来算,不循环的当然补零很好理解;至于想要证明,去百度百科吧;

此题没有明确告诉你循环节在哪,需要自己寻找最小的分母,即为答案;故用一个循环,枚举所有循环节;

#include<iostream>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
typedef long long int ll;
const int N = 1005;
int GCD(int x,int y) {
    return x%y==0?y:GCD(y,x%y);
}
int main() {
    char s[N];
//    int i=2;
//    cout<<pow(10.0,i);
    while(~scanf("%s",s)&&strcmp(s,"0")){
        int length=0,len=strlen(s);
        ll num=0;
        for(int i=2;i<len&&s[i]!='.';i++){   //length记录字符串小数点后多少位; 
            num=num*10+s[i]-'0';              //num记录小数点后的总数值,如果小数点后数字很多,此方法不行,应该继续沿用字符串 
            length++;
        }

        ll cnt,res,x,y,ans_x,ans_y=0x3f3f3f3f,gcd;
         double k;               //pow一定要用double来接,不然会损失精度,例如:pow(10,i)分别为:1,10,99,1000...;不信的可自己去试试; 
        for(int i=0;i<length;i++){   // i代表循环的数有多少位 
            y=0;
            k=pow(10.0,i);         
            //cnt=num/10;
            cnt=num/pow(10.0,length-i);//cnt代表不循环 
            //res=num-cnt;
            x=num-cnt;     //分子等于 总数-不循环的数; 

            for(int j=1;j<=length-i;j++)
                y=y*10+9;            
            y*=k;           //y为分母 
            gcd=GCD(x,y);
            x/=gcd;
            y/=gcd;
            if(y<ans_y){
                ans_y=y;
                ans_x=x;
            }

        }
        cout<<ans_x<<'/'<<ans_y<<endl;
    }
    //cout << "Hello world!" << endl;
    return 0;
}

F题:http://poj.org/problem?id=3421

题意:给你一个数,求满足 xn%xn-1==0的最长长度;就是说从1-x中,每一项要是前一项的倍数;即求长度,和满足这种链的链数;

例如100;有50-25-5-1;本身不算;

ps:链数就是因数的个数:因为每一次可以被整除,就是一个因数;数量就是改因数的的全排列去重:该链从1开始,每次选择可乘一个因数,如果每个因数都不同,当然有ANN种不同的数,但是如果因数重合,就要去重,比如2,2,5,5,你1的第二项要么5,要么2;

#include <iostream>
#include <algorithm>
#include <stack>
#include <stdio.h>
#include<cstring>
#include<string.h>
using namespace std;
long long int f[22];
void ff(){
    f[0]=1;
    f[1]=1;
    for(int i=2;i<=21;i++) //阶乘 打表 
    f[i]=i*f[i-1];
}
int main() {
    ff();
    int n;
    while(cin>>n) {
        long long int k=0,ans=1;
        
        for(int i=2;i*i<=n;i++){
            if(n%i==0){
                int ecount=0;
                while(n%i==0){  //求有多少个因数 
                    ecount++;  //相同的因数相加; 
                    n/=i;
                }
                ans*=f[ecount]; //ans为去重; 
                k+=ecount; //k为总因数个数; 
            }
        }
        if(n>1)k+=1;
        cout<<k<<' '<<f[k]/ans<<endl;
    }
    return 0;
}

G题:http://poj.org/problem?id=3292

题意:给你一个H数,求从1-n中只能被  2个H数  分解的数  的个数;就是说这个世界只有H数,4n+1的数为H数;

ps:打表法,不然超时,例如5*5=25,25算一个但是125=5*5*5不算,也就是说125=5*25就不算;

用nuber代表里面条件成立的,走循环,i+=4即可;当第一次出现时,记number[i*j]满足条件,一旦出现以及满足条件的number,则i*j不满足条件,记为-1;

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1000021;
int p[N];
int number[N];

void h_prime() {
	for(int i=5; i<N; i+=4) {
		for(int j=i; j<N; j+=4) {
			if(i>(N/j))break;
			if(number[i]==0&&number[j]==0)  //如果第一次出现,将代表此i,j不能被h数分解; 
				number[i*j]=1;          //记i*j=1;符合条件 
			else
				number[i*j]=-1;      //如果i或者j已经被标记为1,此时i*j就可以被分为3或3个以上的h数,不满足条件; 
		}
	}
}

void work() {                          //递推记录有多少个,也要打表; 
	for(int i=25; i<N; i+=4){
		if(number[i]==1)
			p[i]=p[i-4]+1;
		else
		p[i]=p[i-4];
	}
		
	 
}
int main() {
	int m;
	int tot=0;
	h_prime();
	work();
	while(~scanf("%d",&m)&&m) {
		cout<<m<<' '<<p[m]<<endl;

	}
	return 0;
}

H题:http://poj.org/problem?id=3641

题意:给p,a,当pow(a,p)%p==a,并且p不是素数,则YES;

ps:快速幂,求解;

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long int ll;

bool prime(ll n){
	if(n==2||n==3)return false;
	for(int i=2;i*i<=n;i++){
		if(n%i==0)return true;
	}
	return false;
}
ll  poww(ll x,ll y,ll mod){ //快速幂模板; 
	ll res = x , ans = 1;
	while(y){
		if( y & 1){
			ans%=mod;
			ans*=res;
		}
		//res%=mod;
		res=(res*res)%mod;
		y/=2;
	}
	return ans%mod;
}
int main(){
	ll a,b;
	while(scanf("%I64d%I64d",&b,&a)!=EOF&&b||a){
		ll cnt = poww(a,b,b);
		if(!prime(b))
		cout<<"no"<<endl;
		else if(cnt==a)
		cout<<"yes"<<endl;
		else 
		cout<<"no"<<endl;
	}
	return 0;
}

j题:http://acm.hdu.edu.cn/showproblem.php?pid=2049

题意:n对新娘中(也就是n对新郎),有M个新郎选错新娘的方案数;

ps:递推:可以说如果现在  已经有n-1个人选错了,那么第n个人加入的时候,随便拿自己的新郎和n-1个新郎更换,则有n个新郎选错,故n-1个方案,或者n-2个人已经选错的时候,第n个新郎拿自己的新娘和第n-1个人换,每个人都可能是那第n-1个人,那么也是n个新郎选错,故f[n]=(n-1)*(f[n-1]+f[n-2]);

方案数:先选n-m个对的人出来,C(N,M)即,故答案为c(n,m)*f[n];

#include<iostream>
using namespace std;
typedef long long ll;
const int maxn=30;
ll f[maxn];
ll c[maxn][maxn];
void work(){
    c[0][0]=1;
    for(int i=1;i<=20;i++){     //代码简单,不做解释 
        for(int j=0;j<=i;j++){
            c[i][j]=c[i-1][j-1]+c[i-1][j];
        }
    }
    f[0]=0;
    f[1]=0;f[2]=1;
    for(int i=3;i<=20;i++)
        f[i]=(i-1)*(f[i-1]+f[i-2]);

}
int main(){
    work();
    int _;
    cin>>_;
    while(_--){
        int n,m;
        cin>>n>>m;
        cout<<c[n][m]*f[m]<<endl;
    }
    return 0;
}
发布了97 篇原创文章 · 获赞 3 · 访问量 9441

猜你喜欢

转载自blog.csdn.net/foolishpichao/article/details/98352339