当前位置: 代码迷 >> 电脑整机及配件 >> Tutorial CodeForces Round 289 (Div.2) (Second Winter Computer Camp Selection 2015) 例题
  详细解决方案

Tutorial CodeForces Round 289 (Div.2) (Second Winter Computer Camp Selection 2015) 例题

热度:542   发布时间:2016-04-29 02:40:32.0
Tutorial CodeForces Round 289 (Div.2) (Second Winter Computer Camp Selection 2015) 题解

题目链接:点击打开链接

A:

#include <cstdio>#include <vector>#include <algorithm>#include <iostream>#include <map>#include <set>#include <queue>#include <cstring>#include <cmath>#include <string>using namespace std;int a[12][11];int main() {    for (int i = 0; i <= 10; ++i) a[i][0] = a[0][i] = 1;    for (int i = 1; i <= 10; ++i) {        for (int j = 1; j <= 10; ++j) {            a[i][j] = a[i - 1][j] + a[i][j - 1];        }    }    int n;    scanf("%d", &n);    printf("%d\n", a[n - 1][n - 1]);    return 0;}
B:构造

#include <cstdio>#include <vector>#include <algorithm>#include <iostream>#include <map>#include <set>#include <queue>#include <cstring>#include <cmath>#include <string>using namespace std;typedef long long ll;const int N = 105;int n, m;int a[N];int main() {    while (~scanf("%d %d", &n, &m)){        int mi = 1000, mx = 0;        for (int i = 1; i <= n; i++){            scanf("%d", &a[i]);            mi = min(mi, a[i]);            mx = max(mx, a[i]);        }        if (mx - mi > m)puts("NO");        else {            puts("YES");            for (int i = 1; i <= n; i++){                for (int j = 1; j <= mi; j++)printf("%d ", 1);                a[i] -= mi;                for (int j = 1; j <= a[i]; j++)printf("%d ", j); puts("");            }        }    }    return 0;}
C:模拟

题意:有一个n长的严格单调递增序列,对于序列上某个点的权值就是数位和(即 123的数位和为6)

现在给出这个序列的数位和,构造一个序列使得最后一个数最小。

略麻烦,首先我们得到一个结论:对于给定的sum[i],我们目标是构造最小的且比前面的数大的数。

一定是构造最小的数,因为大的数我们也能用sum[i]构造,倒不如构造最小的。

构造时先判断是否需要进位(即位数能不能和上一个数字一样)

然后暴力递增即可。

#include <cstdio>#include <vector>#include <algorithm>#include <iostream>#include <map>#include <set>#include <queue>#include <cstring>#include <cmath>#include <string>using namespace std;typedef long long ll;const int N = 305;int n;int Ni(vector<int>&x){//返回最低位且不为9的位置,若全为9返回-1    for (int i = 0; i < x.size(); i++)if (x[i] != 9)return i;    return -1;}void add(vector<int>&x){//让x的数位和增加1    int ni = Ni(x);     if (ni == -1){//全为9时想要让数位和增加1只能在最高位添一个1        x.push_back(1);    }    else {        x[ni]++;    }}void hehe(vector<int>&now, vector<int>&old, int sum, int l){//当位数比上一个数字要大时,我们先构造一个100···这样的序列,且使得这个序列位数最少且全为9时的数位和>=sum,然后暴力增加数位和即可    int dig = old.size() + 1;    while (dig * 9 < sum){        dig++;    }    dig--;    now.clear();    while (dig--)now.push_back(0); now.push_back(1);    sum--;    while (sum--)add(now);}void work(vector<int>&now, vector<int>&old, int sum,int l){    if (l < sum){//如果数位和已经比上一个数大就直接从上一个数开始增加数位和        now = old;        sum -= l;        while (sum--)add(now);        return;    }    else {        if (Ni(old) == -1 || old.size() * 9 < sum){            hehe(now, old, sum, l);            return;        }        now = old;        int s = 0;        int find = -1;        for (int i = now.size()-1; i >= 0; i--){//如果我们把上一个数的某一位 find 增加1,然后把个位到find位全变0,能使得数位和<=sum 那么我们就不必增加位数,否则还是要增加位数            s += now[i];            if (now[i] < 9 && s + 1 <= sum){                find = i;            }        }        if (find!=-1){            now[find]++;            for (int i = 0; i < find; i++)now[i] = 0;            int ssum = sum;            for (int i = 0; i < now.size(); i++)ssum -= now[i];            if (ssum >= 0){                while (ssum--){ add(now); }                for (int i = now.size() - 1; i >= 0; i--)if (now[i]>old[i])                return;                else if (now[i] < old[i])break;            }        }        hehe(now, old, sum, l);         }}vector<int>u[2];int main() {    while (~scanf("%d", &n)){        u[0].clear(); u[1].clear();        u[1].push_back(0);        int cur = 0, last = 1;        int sum, l = 0;        while (n--){            scanf("%d", &sum);            work(u[cur], u[last], sum, l);            for (int i = u[cur].size() - 1; i >= 0; i--)putchar('0' + u[cur][i]);            puts("");            l = sum;            cur ^= 1; last ^= 1;        }    }    return 0;}/*5111116*/
D:

import java.util.*;public class D {    public static void main(String[] args) {        Scanner in = new Scanner(System.in);        int n = in.nextInt();        int m = in.nextInt();        long[][] w = new long[n][m];        for (int i = 0; i < n; i++) {            for (int j = 0; j < m; j++) {                w[i][j] = in.nextLong();            }        }        // check a k constraint        // delta for ai - a0 in each j        boolean possible = true;        Long k = null;        for (int i = 1; i < n; i++) {            Set<Long> deltas = new TreeSet<Long>();            for (int j = 0; j < m; j++) {                deltas.add(w[i][j] - w[0][j]);            }            if (deltas.size() > 2) {                possible = false;                break;            } else if (deltas.size() == 2) {                Iterator<Long> iterator = deltas.iterator();                long one = iterator.next();                long two = iterator.next();                if (one * two > 0) {                    possible = false;                    break;                } else {                    long possibleK = Math.abs(one - two);                    if (k == null) {                        k = possibleK;                    } else if (k != possibleK) {                        possible = false;                        break;                    }                }            }        }        // check b k constraint        // delta for bj - b0 in each i        for (int j = 1; j < m; j++) {            Set<Long> deltas = new TreeSet<Long>();            for (int i = 0; i < n; i++) {                deltas.add(w[i][j] - w[i][0]);            }            if (deltas.size() > 2) {                possible = false;                break;            } else if (deltas.size() == 2) {                Iterator<Long> iterator = deltas.iterator();                long one = iterator.next();                long two = iterator.next();                if (one * two > 0) {                    possible = false;                    break;                } else {                    long possibleK = Math.abs(one - two);                    if (k == null) {                        k = possibleK;                    } else if (k != possibleK) {                        possible = false;                        break;                    }                }            }        }        // double check k        if (k != null && possible) {            for (int i = 0; i < n; i++) {                for (int j = 0; j < m; j++) {                    if (w[i][j] >= k) {                        possible = false;                    }                }            }        }        //        if (possible) {            System.out.println("YES");            if (k == null) {                k = 10000000000000L;            }            System.out.println(k);            long a0 = k;            StringBuilder aString = new StringBuilder();            aString.append(a0);            for (int i = 1; i < n; i++) {                aString.append(' ').append(a0 + (w[i][0] - w[0][0]));            }            System.out.println(aString.toString());            long b0 = k + w[0][0];            StringBuilder bString = new StringBuilder();            bString.append(b0);            for (int j = 1; j < m; j++) {                bString.append(' ').append(b0 + (w[0][j] - w[0][0]));            }            System.out.println(bString.toString());        } else {            System.out.println("NO");        }    }}



E:

#include <cstdio>#include <vector>#include <algorithm>#include <iostream>#include <map>#include <set>#include <queue>#include <cstring>#include <cmath>#include <string>using namespace std;const int MAX_N = 500007;int bit[MAX_N << 1], len;int sum(int i) {    int s = 0;    while (i > 0) {        s += bit[i];        i -= i & -i;    }    return s;}void add(int i, int x) {    while (i <= len) {        bit[i] += x;        i += i & -i;    }}char str[MAX_N];bool is(char ch) {    return ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' ||    ch == 'U' || ch == 'Y';}long long z[MAX_N];long long zz[MAX_N];int main() {    scanf("%s", str + 1);    len = strlen(str + 1);    for (int i = 1; str[i]; ++i) {        if (is(str[i])) z[i] = z[i - 1] + 1;        else z[i] = z[i - 1];    }    for (int i = 1; i <= len; ++i) {        zz[i] = zz[i - 1] + z[i];    }        double ans = 0;    for (int i = 0; i <= len; ++i) {        if (len - (i + 1) >= 0)             ans += (zz[len] - zz[len - (i + 1)] - (zz[i])) * 1. / (i + 1);        }    printf("%f\n", ans);    return 0;}


F:dp[l][r]表示 区间[l,r] 构成一棵树的方法数。

对于一个区间[l, r] 构成一棵树,则点l一定是根,然后枚举2个区间相乘即可

dp[l][r] = dp[l+1][i] * dp[i+1][r] ( i = [l+1, r] )

当然 a[i+1] > a[l+1] ,这样才会满足题目中的暴力代码。。==

import java.io.PrintWriter;import java.text.DecimalFormat;import java.util.ArrayList;import java.util.Arrays;import java.util.Collections;import java.util.Comparator;import java.util.HashMap;import java.util.Iterator;import java.util.LinkedList;import java.util.Map;import java.util.PriorityQueue;import java.util.Scanner;import java.util.Stack;import java.util.TreeMap;import java.util.TreeSet;import java.util.Queue;public class Main {	int n;	int[] a = new int[N];	long[][] dp = new long[N][N];	long dfs(int l, int r){		if(dp[l][r] != -1)return dp[l][r];		if(l >= r)return dp[l][r] = 1;		long ans = 0;		for(int i = l+1; i <= r; i++)			if(i == r || a[i + 1] > a[l + 1])				ans = (dfs(l+1, i) * dfs(i, r)+ans)%mod;			return dp[l][r] = ans;	}	void work() {		while(cin.hasNext()){			n = cin.nextInt(); for(int i = 1; i <= n; i++)a[i] = cin.nextInt();			for(int i = 1; i <= n; i++){				for(int j = i; j <= n; j++)dp[i][j] = -1;			}			System.out.println(dfs(1, n));		}	}	Main() {		cin = new Scanner(System.in);		out = new PrintWriter(System.out);	}	public static void main(String[] args) {		Main e = new Main();		e.work();		out.close(); 	}	public Scanner cin;	public static PrintWriter out;	static int N = 505;	DecimalFormat df=new DecimalFormat("0.0000");	static int mod = 1000000007 ;}







  相关解决方案