惹某人熬不过de集训第六周(习题+感悟)

(一)java从入门到入土(并不)

A - N! HDU - 1042

    Given an integer N(0 ≤ N ≤ 10000), your task is to calculate N!

Input

    One N in one line, process to the end of file.

Output

    For each N, output N! in one line.

Sample Input

1
2
3

Sample Output

1
2
6

AC代码

import java.util.*; 
import java.math.*;
public  class Main{
	public static void main(String[] args){
		Scanner input = new Scanner(System.in);
		while(input.hasNext()){
			int n = input.nextInt();
			BigInteger cnt = BigInteger.ONE;
			for(int i = 1;i <= n;i++)
				cnt = cnt.multiply(BigInteger.valueOf(i));
			System.out.println(cnt);
		}
	}
}

B - Integer Inquiry HDU - 1047

    One of the first users of BIT’s new supercomputer was Chip Diller. He extended his exploration of powers of 3 to go from 0 to 333 and he explored taking various sums of those numbers.
    `This supercomputer is great,’’ remarked Chip. ``I only wish Timothy were here to see these results.’’ (Chip moved to a new apartment, once one became available on the third floor of the Lemon Sky apartments on Third Street.)

Input

    The input will consist of at most 100 lines of text, each of which contains a single VeryLongInteger. Each VeryLongInteger will be 100 or fewer characters in length, and will only contain digits (no VeryLongInteger will be negative).
    The final input line will contain a single zero on a line by itself.

Output

    Your program should output the sum of the VeryLongIntegers given in the input.
    This problem contains multiple test cases!
    The first line of a multiple input is an integer N, then a blank line followed by N input blocks. Each input block is in the format indicated in the problem description. There is a blank line between input blocks.
    The output format consists of N output blocks. There is a blank line between output blocks.

Sample Input

1
123456789012345678901234567890
123456789012345678901234567890
123456789012345678901234567890
0

Sample Output

370370367037037036703703703670

理解

这就是一道简单的大数求和	,所以就java好啦

AC代码

import java.util.*; 
import java.math.*;
public  class Main{
	public static void main(String[] args){
		Scanner input = new Scanner(System.in);
		int n = input.nextInt();
		while(n-->0){
			BigInteger cnt = new BigInteger("0");
			while(input.hasNextBigInteger()){
				BigInteger t = new BigInteger("0");
				t = input.nextBigInteger();
				if(!t.equals(BigInteger.valueOf(0))){
					cnt = cnt.add(t);
				}
				else{
					System.out.println(cnt);
					if(n!=0) System.out.println();
					break;
				}
			}	
		}
		input.close();
	}
}

C - Exponentiation HDU - 1063

    Problems involving the computation of exact values of very large magnitude and precision are common. For example, the computation of the national debt is a taxing experience for many computer systems.
    This problem requires that you write a program to compute the exact value of R n where R is a real number ( 0.0 < R < 99.999 ) and n is an integer such that 0 < n <= 25.

Input

    The input will consist of a set of pairs of values for R and n. The R value will occupy columns 1 through 6, and the n value will be in columns 8 and 9.

Output

    The output will consist of one line for each line of input giving the exact value of R^n. Leading zeros should be suppressed in the output. Insignificant trailing zeros must not be printed. Don’t print the decimal point if the result is an integer.

Sample Input

95.123 12
0.4321 20
5.1234 15
6.7592 9
98.999 10
1.0100 12

Sample Output

548815620517731830194541.899025343415715973535967221869852721
.00000005148554641076956121994511276767154838481760200726351203835429763013462401
43992025569.928573701266488041146654993318703707511666295476720493953024
29448126.764121021618164430206909037173276672
90429072743629540498.107596019456651774561044010001
1.126825030131969720661201

AC代码

import java.util.*; 
import java.math.*;
public  class Main{
	public static void main(String[] args){
		Scanner input = new Scanner(System.in);
		BigInteger [] f = new BigInteger[1005];
		f[1] = new BigInteger("1");
		f[2] = new BigInteger("2");
		for(int i = 3;i < 1005;i++){
			f[i] = f[i - 1].add(f[i - 2]);
		}
		while(input.hasNext()){
			BigInteger x = input.nextBigInteger();
			BigInteger y = input.nextBigInteger();
			BigInteger zero = new BigInteger("0");
			if(x.compareTo(zero) == 0 && y.compareTo(zero) == 0) break;
			int ans = 0;
			for(int i = 1;i < 1005;i++){
				if(f[i].compareTo(x) < 0) continue;
				if(f[i].compareTo(y) > 0) break;
				ans++;
			}
			System.out.println(ans);
		}
		input.close();
	}
}

D - Rightmost Digit HDU - 1061

    Given a positive integer N, you should output the most right digit of N^N.

Input

    The input contains several test cases. The first line of the input is a single integer T which is the number of test cases. T test cases follow.
    Each test case contains a single positive integer N(1<=N<=1,000,000,000).

Output

    For each test case, you should output the rightmost digit of N^N.

Sample Input

2
3
4

Sample Output

7
6

Hint

In the first case, 3 * 3 * 3 = 27, so the rightmost digit is 7.
In the second case, 4 * 4 * 4 * 4 = 256, so the rightmost digit is 6.

AC代码

import java.util.*; 
import java.math.*;
public  class Main{
	public static void main(String[] args){
		Scanner input = new Scanner(System.in);
		int t = input.nextInt();
		for(int i = 0;i < t;i++){
			int n = input.nextInt();
			int tim = n;
			if(n > 10) n %= 10;
			int res = 1;
			if(n == 0){
				System.out.println(n);
				continue;
			}
			if(n == 1 || n == 5 || n == 6){
				System.out.println(n);
				continue;
			}
			else{
				if(n == 4 || n == 9){
					tim %= 2;
					if(tim == 0) tim = 2;
				}
				else{
					tim %= 4;
					if(tim == 0) tim = 4;
				}
			}
			while(tim-->0){
				if(res < 10){
					res *= n;
				}
				else res = (res%10)*n;
			}
			System.out.println(res%10);
		}
		input.close();
	}
}

(二)有趣的题目

A - 【数组】准确计算自然数N的阶乘(N≤50)

题目描述

    对于自然数N的阶乘,当N比较小时,可以32位整数int范围内准确表示
    例如12!=479001600<2147483647(231-1)
    而20!=2432902008176640000<9223372036854775807(263-1)可以在64位整数long long int范围内准确表示
    但是N取值更大时,N!只能使用浮点数计算,从而产生误差
    要求:输入自然数N(N≤50),准确计算自然数N的阶乘
    说明50!≈3.04e+64,可以考虑定义数组存储计算结果的各位数字
对比摘录B题的N!由于数字太大用java来处理

Input

测试数据有多组,处理到输入结束

Output

每个输出占1行

Sample Input

1
10
20
29
30

Sample Output

1
3628800
2432902008176640000
8841761993739701954543616000000
265252859812191058636308480000000

AC代码(c++)

#include<bits/stdc++.h>
using namespace std;
const int N = 1000 + 5;
 
int main(){
    int n;
    while(cin >> n){
        int a[N];
        memset(a,0,sizeof(a));
        a[1] = 1;
        a[0] = 1;
        int i,j;
        for(i = 2;i <= n;i++){
            int k = 0;
            for(j = 1;j <= a[0];j++){
                a[j] = a[j] * i + k;
                k = a[j] / 10;
                a[j] %= 10;
            }
            while(k > 0){
                a[j] = k % 10;
                k /= 10;
                j++;
            }
            a[0] = j - 1;
        }
        for(int i = a[0];i >= 1;i--) cout << a[i];
        cout << endl;
    }
    return 0;
}

B - 阶乘最后k位

    n的阶乘定义为n!=123*……*n 如3!=6 n!通常最后会有很多0,如5!=120 最后有一个0,现在统计n!去除末尾的0后,最后k位是多少

Input

     第一行包括两个数n,k

Output

    如果n!不止k位,则输出最后k位,如果不足k位,则高位补零,补足k位后输出 注意!这里与阶乘统计1有区别!

Sample Input

7 2

Sample Output

04

提示

7!为5040,去除末尾的0为504,最后两位为04 100%满足1< =n< =1400000 1< =k< =10

AC代码

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n,k;
    char a[105];
    cin >> n >> k;
    long long ans = 1;
    for(int i = 2;i <= n;i++){
        ans *= i;
        while(ans % 10 == 0) ans /= 10;
        ans %= 10000000000;
    }
    for(int i = 0;i < k;i++){
        if(ans){
            a[i] = ans % 10 + 48;
            ans /= 10;
        }
        else a[i] = '0';
    }
    for(int i = k-1;i >= 0;i--) cout << a[i];
    cout << endl;
    return 0;
}

C - 阶乘和(sum)

    已知正整数N(N<=100),设S=1!+2!+3!+…N!。其中"!"表示阶乘,即N!=123*……(N-1)N,如:3!=123=6。请编程实现:输入正整数N,输出计算结果S的值。

Sample Input

4

Sample Output

33

AC代码

#include<bits/stdc++.h>
using namespace std;
const int N = 100000 + 5;
int main(){
    int n;
    int a[N]={0},ans[N]={0};
    while(cin >> n){
        memset(ans,0,sizeof(ans));
        ans[0] = 1;
        for(int i = 1;i <= n;i++){
            memset(a,0,sizeof(a));
            a[1] = 1;
            int y = 1;
            int temp;
            for(int j = 2;j <= i;j++){
                int k;
                for(k = 1,temp = 0;k <= y;k++){
                    a[k] = a[k]*j + temp;
                    temp = a[k] / 10;
                    a[k] %= 10; 
                }
                while(temp > 0){
                    a[k] = temp % 10;
                    temp /= 10;
                    k++;
                }
                y = k - 1;
            }
            for(int x = 1;x <= y;x++) ans[x] += a[x];
            for(int x = 0;x < ans[0];x++){
                if(ans[x+1] >= 10){
                    ans[0]++;
                }
                if(ans[x] >= 10){
                    ans[x+1] += ans[x] / 10;
                    ans[x] %= 10;
                }
            }
        }
        for(int i = ans[0];i >= 1;i--) cout << ans[i];
        cout << endl;
    }
    return 0;
}

D - 高精度求积

    输入两个高精度正整数M和N(M和N均小于100位),求这两个高精度数的积。

Sample Input

36
3

Sample Output

108

AC代码

#include<bits/stdc++.h>
using namespace std;
const int N = 100000 + 5;
int main(){
    int a[N],b[N],c[N];
    string s1,s2;
    cin >> s1 >> s2;
    if(s1[0] == '0' || s2[0] == '0'){
        cout << 0 << endl;
        return 0;
    }
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
    memset(c,0,sizeof(c));
    int l1 = s1.length(); int l2 = s2.length();
    for(int i = 0;i <= l1 - 1;i++) a[l1-i] = s1[i]-'0';
    for(int i = 0;i <= l2 - 1;i++) b[l2-i] = s2[i]-'0';
    for(int i = 1;i <= l2;i++){
        int k = 0;
        for(int j = 1;j <= l1;j++){
            c[i+j-1] += a[j]*b[i];
            k = c[i+j-1] / 10;
            c[i+j-1] %= 10;
            c[i+j] += k;
        }
    }
    int x = l1 + l2;
    for(int i = l1+l2;i >= 2;i--){
        if(c[i] != 0) break;
        else x--;
    }
    for(int i = x;i >= 1;i--) cout << c[i];
    cout << endl;
    return 0;
}

E - 回文数

题目描述

    若一个数(首位不为零)从左向右读与从右向左读都是一样,我们就将其称之为回文数。例如:给定一个 10进制数 56,将 56加 65(即把56从右向左读),得到 121是一个回文数。又如,对于10进制数87,
    STEPl: 87+78= 165
    STEP2: 165+561= 726
    STEP3:726+627=1353
    STEP4:1353+3531=4884
  在这里的一步是指进行了一次N进制的加法,上例最少用了4步得到回文数4884。
    写一个程序,给定一个N(2<N<=10或N=16)进制数 M.求最少经过几步可以得到回文数。如果在30步以内(包含30步)不可能得到回文数,则输出“Impossible”

Input

    输入有2行,第1行表示R进制;第2行表示输入的自然数。

Output

    输出只有1行,如果在n步以内(n<=30)得到回文数,则输出STEP=n
    否则输出“Impossible”

Sample Input

9
87

Sample Output

STEP=6

AC代码

#include<bits/stdc++.h>
using namespace std;
int n,l,a[1005],cnt;
string x;
int pd(int l){ //判断是否为回文串 
    for(int i = 0;i < l/2;i++)
        if(a[i] != a[l-i-1]) return 0;
    return 1;
}
int f(int l){
    int b[10005] = {0},k = 0;
    for(int i = 0;i < l;i++){
        b[i] += a[i] + a[l-i-1];
        b[i+1] = b[i] / n; //n进制 
        b[i] %= n;
    }
    if(b[l] != 0) l++;
    for(int i = l - 1;i >= 0;i--) a[k++] = b[i];
    return l;
}
int main(){
    cin >> n >> x;
    cnt = 0;
    memset(a,0,sizeof(a));
    l = x.length();
    for(int i = 0;i < l;i++){ //判断是否为 16进制 
        if(x[i] < 'A') a[i] = x[i] - '0';
        else a[i] = x[i] -'A' + 10;
    }
    while(cnt <= 30){
        cnt++;
        l = f(l);
        if(pd(l)){
            cout << "STEP=" << cnt << endl;
            return 0;
        }
    }
    cout << "Impossible" << endl;
    return 0;
}

F - LCM Walk HDU - 5584

    A frog has just learned some number theory, and can’t wait to show his ability to his girlfriend.
    Now the frog is sitting on a grid map of infinite rows and columns. Rows are numbered 1,2,⋯ from the bottom, so are the columns. At first the frog is sitting at grid (sx,sy), and begins his journey.
    To show his girlfriend his talents in math, he uses a special way of jump. If currently the frog is at the grid (x,y), first of all, he will find the minimum z that can be divided by both x and y, and jump exactly z steps to the up, or to the right. So the next possible grid will be (x+z,y), or (x,y+z).
    After a finite number of steps (perhaps zero), he finally finishes at grid (ex,ey). However, he is too tired and he forgets the position of his starting grid!
    It will be too stupid to check each grid one by one, so please tell the frog the number of possible starting grids that can reach (ex,ey)!

Input

    First line contains an integer T, which indicates the number of test cases.
    Every test case contains two integers ex and ey, which is the destination grid.
⋅ 1≤T≤1000.
⋅ 1≤ex,ey≤109.

Output

    For every test case, you should output " Case #x: y", where x indicates the case number and counts from 1 and y is the number of possible starting grids.

Sample Input

3
6 10
6 8
2 8

Sample Output

Case #1: 1
Case #2: 2
Case #3: 3

理解

	给出终点坐标(ex,ey),假设当前位置是(x,y),只能向右走或者向下走,走到(x+k,y)或者(x,y+k),k=lcm(x,y) 
	令gcd(x,y)=t,x=nt,y=mt,lcm(x,y)=nmt,那么下一步能走到(n(m+1)t,mt)或者(nt,m(n+1)t)
	并且由于n(m+1)与m互质,n与m(n+1)互质,所以gcd依然是t.
	用逆推找出答案,每次都假设x>y,x=nt,y=mt,当前点就是由(x/(y/t+1),y)走到的,如果x不再是(y+t)的倍数(即:(y/k+1)*t的倍数),则表示不能再逆推

AC代码

#include <bits/stdc++.h>
using namespace std;
int gcd(int a,int b){ //求最大公约数 
	return b ? gcd(b,a%b) : a;
}
int main(){
	int t;
	cin >> t;
	for(int r = 1;r <= t;r++){
		int x,y;
		cin >> x >> y;
		if(x < y) swap(x,y);
		int k = gcd(x,y);
		int ans = 1;
		while(x % (y+k) == 0){
			ans++;
			x = x / (y / k + 1);
			if(x < y) swap(x,y);
		}
		cout << "Case #" << r << ": " << ans << endl;
	}
	return 0;
}

G - A sequence of numbers HDU - 2817

    Xinlv wrote some sequences on the paper a long time ago, they might be arithmetic or geometric sequences. The numbers are not very clear now, and only the first three numbers of each sequence are recognizable. Xinlv wants to know some numbers in these sequences, and he needs your help.

Input

    The first line contains an integer N, indicting that there are N sequences. Each of the following N lines contain four integers. The first three indicating the first three numbers of the sequence, and the last one is K, indicating that we want to know the K-th numbers of the sequence.
    You can assume 0 < K <= 10^9, and the other three numbers are in the range [0, 2^63). All the numbers of the sequences are integers. And the sequences are non-decreasing.

Output

    Output one line for each test case, that is, the K-th number module (%) 200907.

Sample Input

2
1 2 3 5
1 2 4 5

Sample Output

5
16

理解

第一个数组代表下面有几组样例
然后下面是四个数,其中前三个就是数组序列的前三个数,你需要根据这三个数来推断这个序列的规律(如等差数列,等比数列)
第四个数字是要求你输出的序列的第几个数

AC代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll d = 200907;
ll f(ll a,ll b){
	ll cnt = 1;
	while(b){
		if(b % 2){
			cnt *= a;
			cnt %= d;
		}
		a *= a;
		a %= d;
		b /= 2;
	}
	return cnt;
}
int main(){
	int n;
	cin >> n;
	while(n--){
		ll a[4];
		cin >> a[1] >> a[2] >> a[3];
		ll m;
		cin >> m;
		if(a[2] - a[1] == a[3] - a[2] && a[2] - a[1] > 0){
			ll k = a[2] - a[1];
			cout << ( ( ((m - 1)%d) * (k%d) )% d + a[1] % d ) % d<< endl;	
		}
		else
			cout << ( (a[1]%d) * (f(a[2]/a[1],m-1)%d) ) % d << endl;
	}
	return 0;
} 

H - 青蛙的约会 POJ - 1061

    两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面。它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止。可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置。不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的。但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的。为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面。
我们把这两只青蛙分别叫做青蛙A和青蛙B,并且规定纬度线上东经0度处为原点,由东往西为正方向,单位长度1米,这样我们就得到了一条首尾相接的数轴。设青蛙A的出发点坐标是x,青蛙B的出发点坐标是y。青蛙A一次能跳m米,青蛙B一次能跳n米,两只青蛙跳一次所花费的时间相同。纬度线总长L米。现在要你求出它们跳了几次以后才会碰面。

Input

    输入只包括一行5个整数x,y,m,n,L,其中x≠y < 2000000000,0 < m、n < 2000000000,0 < L < 2100000000。

Output

    输出碰面所需要的跳跃次数,如果永远不可能碰面则输出一行"Impossible"

Sample Input

1 2 3 4 5

Sample Output

4

理解

	假设两个青蛙跳了t次之后终于会面了,也就是说 x+m*t≡y+n*t (mod L)
	变形之后得到模线性方程:(m-n)*t≡y-x (mod L)
	这个方程有解的充分必要条件是 m-n和L的最大公约数gcd(m-n,L)能够被y-x整除。

AC代码

#include <iostream>
using namespace std;
typedef long long ll;
ll f(ll a,ll b,ll &x,ll &y){
	if(b == 0){
		x = 1;
		y = 0;
		return a;
	}
	ll k = f(b,a%b,x,y);
	ll t = x - a/b*y;
	x = y;
	y = t;
	return k;
}

int main(){
	ll x,y,m,n,l,X,Y;
	while(cin >> x >> y >> m >> n >> l){
		ll p = f(n-m,l,X,Y);
		ll r = l / p;
		if((x-y)%p) cout << "Impossible" << endl;
		else cout << ((x-y)/p*X%r+r) % r << endl;
	}	
	return 0;
}

I - Max Factor HDU - 2710

    To improve the organization of his farm, Farmer John labels each of his N (1 <= N <= 5,000) cows with a distinct serial number in the range 1…20,000. Unfortunately, he is unaware that the cows interpret some serial numbers as better than others. In particular, a cow whose serial number has the highest prime factor enjoys the highest social standing among all the other cows.
    (Recall that a prime number is just a number that has no divisors except for 1 and itself. The number 7 is prime while the number 6, being divisible by 2 and 3, is not).
    Given a set of N (1 <= N <= 5,000) serial numbers in the range 1…20,000, determine the one that has the largest prime factor.

Input

    * Line 1: A single integer, N
    * Lines 2…N+1: The serial numbers to be tested, one per line

Output

    * Line 1: The integer with the largest prime factor. If there are more than one, output the one that appears earliest in the input file.

Sample Input

4
36
38
40
42

Sample Output

38

理解

	本题要求给定的n个数字中拥有最大素因子的数
	只需要存起来每个数最大的素因子即可

AC代码

#include <bits/stdc++.h>
using namespace std;
int a[20005];
void ss(){
	memset(a,0,sizeof(a));
	for(int i = 2;i <= 20005;i++){
		if(!a[i]){
			a[i] = i;
			for(int j = 2;j * i <= 20005;j++){
				a[i*j] = i;
			}
		}
	}
}
int main(){
	int n;
	ss();
	while(cin >> n){
		int x = -1,y = -1;
		for(int i = 0;i < n;i++){
			int t;
			cin >> t;
			if(a[t] > x){
				x = a[t];
				y = t;
			}
		}
		cout << y << endl;
	}
	return 0;
}

J - Find a multiple POJ - 2356

    The input contains N natural (i.e. positive integer) numbers ( N <= 10000 ). Each of that numbers is not greater than 15000. This numbers are not necessarily different (so it may happen that two or more of them will be equal). Your task is to choose a few of given numbers ( 1 <= few <= N ) so that the sum of chosen numbers is multiple for N (i.e. N * k = (sum of chosen numbers) for some natural number k).

Input

    The first line of the input contains the single number N. Each of next N lines contains one number from the given set.

Output

    In case your program decides that the target set of numbers can not be found it should print to the output the single number 0. Otherwise it should print the number of the chosen numbers in the first line followed by the chosen numbers themselves (on a separate line each) in arbitrary order.
    If there are more than one set of numbers with required properties you should print to the output only one (preferably your favorite) of them.

Sample Input

5
1
2
3
4
1

Sample Output

2
2
3

理解

	此题答案不唯一

AC代码

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn = 10000 + 5;
int a[maxn];
int main(){
	int n;
	while(cin >> n){
		for(int i = 0;i < n;i++)
			scanf("%d",&a[i]);
		int sum = 0;
		bool f = 0;
		int x,y;
		for(int i = 0;i < n;i++){
			sum = 0;
			for(int j = i;j < n;j++){
				sum += a[j];
				if(sum % n == 0){
					f = 1;
					x = i;
					y = j;
					break;
				}
			}
			if(f) break;
		}
		if(f){
			cout << y-x+1 << endl;
			for(int i = x;i <= y;i++)
				cout << a[i] << endl;	
		}
		else cout << 0 << endl;
	}
	return 0;
}

K - Prime Distance POJ - 2689

    The branch of mathematics called number theory is about properties of numbers. One of the areas that has captured the interest of number theoreticians for thousands of years is the question of primality. A prime number is a number that is has no proper factors (it is only evenly divisible by 1 and itself). The first prime numbers are 2,3,5,7 but they quickly become less frequent. One of the interesting questions is how dense they are in various ranges. Adjacent primes are two numbers that are both primes, but there are no other prime numbers between the adjacent primes. For example, 2,3 are the only adjacent primes that are also adjacent numbers.
Your program is given 2 numbers: L and U (1<=L< U<=2,147,483,647), and you are to find the two adjacent primes C1 and C2 (L<=C1< C2<=U) that are closest (i.e. C2-C1 is the minimum). If there are other pairs that are the same distance apart, use the first pair. You are also to find the two adjacent primes D1 and D2 (L<=D1< D2<=U) where D1 and D2 are as distant from each other as possible (again choosing the first pair if there is a tie).

Input

    Each line of input will contain two positive integers, L and U, with L < U. The difference between L and U will not exceed 1,000,000.

Output

    For each L and U, the output will either be the statement that there are no adjacent primes (because there are less than two primes between the two given numbers) or a line giving the two pairs of adjacent primes.

Sample Input

2 17
14 17

Sample Output

2,3 are closest, 7,11 are most distant.
There are no adjacent primes.

理解

	找到第一对最接近的两个相邻素数,还要找到两个相邻的素数
	如果存在平局则再次选择第一对

AC代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int maxn = 1e6 + 5;
const int N = 46500;
bool v[maxn];
int numb1 = 0,numb2 = 0;
int pri1[N+5],pri2[maxn]; 
void E_sieve(int k){
	memset(v,false,sizeof(v));
	for(int i = 2;i <= k;i++){
		if(!v[i]){
			pri1[numb1++] = i;
			for(int j = 2*i;j <= k;j+=i)
				v[j] = true;
		}
	}
}
void prime(int l,int r){
	memset(v,false,sizeof(v));
	numb2 = 0;
	if(l < 2) l = 2;
	for(int i = 0;i < numb1 && pri1[i] <= sqrt(r);i++){
		int t = l/pri1[i];
		if(t*pri1[i]<l) t++;
		if(t <= 1) t = 2;
		for(int j = t;(long long)j*pri1[i]<=r;j++){
			v[j*pri1[i]-l] = 1;
		}
	}
	for(int i = 0;i <= r-l;i++){
		if(!v[i]) pri2[numb2++] = i+l;
	}
}
int main(){
	E_sieve(N);
	int l,r;
	while(cin >> l >> r){
		int minn = 0x3f3f3f3f,maxx = -1;
		int a1,a2,b1,b2;
		prime(l,r);
		if(numb2 < 2){
			cout << "There are no adjacent primes." << endl; 
			continue;
		}
		for(int i = 1;i < numb2 && pri2[i] <= r;i++){
			int xx = pri2[i]-pri2[i-1];
			if(xx > maxx){
				a1 = pri2[i-1];
				a2 = pri2[i];
				maxx = xx;
			}
			if(xx < minn){
				b1 = pri2[i-1];
				b2 = pri2[i];
				minn = xx;
			}
		}
		printf("%d,%d are closest, %d,%d are most distant.\n",b1,b2,a1,a2);
	}
	return 0;
}

L - 排列组合 HDU - 1521

    有n种物品,并且知道每种物品的数量。要求从中选出m件物品的排列数。例如有两种物品A,B,并且数量都是1,从中选2件物品,则排列有"AB","BA"两种。

Input

    每组输入数据有两行,第一行是二个数n,m(1<=m,n<=10),表示物品数,第二行有n个数,分别表示这n件物品的数量。

Output

    对应每组数据输出排列数。(任何运算不会超出2^31的范围)

Sample Input

2 2
1 1

Sample Output

2

AC代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
double b[15],f[15],a[15];
double jc(int n){
	double ans = 1;
	for(int i = 1;i <= n;i++){
		ans *= i;
	}
	return ans;
}
int main(){
	int n,m;
	while(cin >> n >> m){
		for(int i = 1;i <= n;i++) cin >> a[i];
		memset(b,0,sizeof(b));
		memset(f,0,sizeof(f));
		for(int i = 0;i <= a[1];i++)
			f[i] = 1.0 / jc(i);
		for(int i = 2;i <= n;i++){ //循环n个物品 
			for(int j = 0;j <= m;j++){ //总共取 m个 
				for(int k = 0;k <= a[i] && j+k<=m;k++){
					// k表示取同一个物品多次 
					b[j+k] += f[j]/jc(k);
				}
			}
			for(int j = 0;j <= m;j++){
				f[j] = b[j];
				b[j] = 0;
			}
		}
		printf("%.0lf\n",f[m]*jc(m));
	}
	return 0;
}

(三)我的感想(die)

关于这周的日常练习

数论杀我,即使我觉得数学还可以(并不),思维量大真令人头秃。
落下的题越来越多了QAq 广度学习下我依旧是一只啥都不懂的辣鸡

关于icpc的网络赛

宁夏这场原题看完北师的ak速度我着实惊呆了。南京的那场我爆零,就很自闭。全程所有题tle,不过和队友的配合好很多了,一起讨论题意,分析的很到位,可惜题目不在能力范围内,就真实的爆零了。的确这些题,分析完发现现有的知识会tle高级算法不会之后,连尝试的勇气都莫得了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值