`
从此醉
  • 浏览: 1055093 次
  • 性别: Icon_minigender_1
  • 来自: US
社区版块
存档分类
最新评论

Codeforces Beta Round #9 (Div. 2 Only)

 
阅读更多

点击打开链接cf#9


A

思路:求gcd然后化简

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

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

int main(){
   int a , b;
   while(scanf("%d%d" , &a , &b) != EOF){
       int tmp = max(a , b);
       tmp = 6-tmp+1;
       int x = gcd(tmp , 6);
       if(x != 1){
         tmp = tmp/x;
         int y = 6/x;
         printf("%d/%d\n", tmp , y);
       }
       else
         printf("%d/6\n" , tmp);
   }
   return 0;
}



B

思路:暴力枚举每一个点
分析:
1 题目要求找到时间最少的那个点,如果有多个找到距离学校最近的点。
2 题目的数据n最大100,而且数据不超10^5,那么我们暴力完全是可以的。
3 注意浮点数的比较问题:#define eps 1e-9 , 现在有两个浮点数a , b
如果if(a-b > eps) a > b , 不可以利用if(b - a < eps) 来判断a > b,只能是第一种
如果if(fabs(a-b) < eps) ,则认为是a = b。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;

#define MAXN 110
#define eps 1e-19

int n , Vb , Vs;
int num[MAXN];
int x , y;

double Dis(int x1 , int y1 , int x2 , int y2){
    return sqrt(1.0*(x1-x2)*(x1-x2)+1.0*(y1-y2)*(y1-y2));
}

int main(){
   while(scanf("%d%d%d" , &n , &Vb , &Vs) != EOF){
       for(int i = 1 ; i <= n ; i++)
          scanf("%d" , &num[i]);
       scanf("%d%d" , &x , &y);
       
       double min = 0x7fffffff;
       int ans;
       double dis;
       for(int i = 2 ; i <= n ; i++){
          double t;
          t = 1.0*num[i]/Vb+Dis(num[i],0,x,y)/Vs;
          if(min - t > eps){/*大于的时候*/
            min = t;
            ans = i;
            dis = Dis(num[i] , 0 , x , y);
          } 
          else if(fabs(t-min) < eps){/*相等*/
            if(dis - Dis(num[i] , 0 , x , y) > eps){
               dis = Dis(num[i] , 0 , x , y);
               ans = i;
            }
          }
       }
       printf("%d\n" , ans);
   }
   return 0;
}




C

思路:1 递归生成数据判断是否大于n 2 打表法
分析:
1 由题目我们可以知道数据有如下规律
1
10 11
100 101 110 111
1000 1001 1010 1011 1100 1101 1110 1111
......
那么我们只要不断的递归生成这些数,直到当前生成的数假设为x ,x>n的时候就return,否则加加ans这样就可以求出个数。

2 打表的话,我们去分析数据就可以得到如下规律
1-9 1个 2^0
10-99 2个 2^1
100-999 4个 2^2
1000-9999 8个 2^3
.......
10^9-999999999 n个 2^9

我们知道2^9不超过1000,那么我们只要利用这些规律把数据保存到一个二维数组即可。假设我们用num[20][1010]来保存,那么就有
num[1][0] = 1;
num[2][0] = 10 , num[2][1] = 11;
num[3][0] = 100 , num[3][1] = 101 , num[3][2] = 110 , num[3][3] = 111;
......
然后对于每一个n,我们只要进行查找即可

3 注意c库函数的pow函数少用,一般自己写pow函数。

代码:

/*递归*/
#include<iostream>
#include<cstdio>
using namespace std;

int n , ans;

void solve(int x){
   if(x > n)
     return;
   ans++;
   solve(x*10);
   solve(x*10+1);
}

int main(){
  while(scanf("%d" , &n) != EOF){
     ans = 0;
     solve(1);
     printf("%d\n" , ans);
  }
  return 0;
}



/*打表*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

#define MAXN 10010

int n;
long long num[20][MAXN];
int vis[20];

/*pow函数*/
int Pow(int x , int y){
   int sum = 1;
   for(int i = 1 ; i <= y ; i++)
      sum *= x;
   return sum;
}

void init(){
    memset(num , 0 , sizeof(num));
    memset(vis , 0 , sizeof(vis));

    for(int i = 1 ; i <= 10 ; i++){
       int k = Pow(2 , i-1);
       vis[i] = vis[i-1] + k;
       int pos = 0;
       
       for(int j = k ; j <= vis[i] ; j++){
          int tmp = 0;
          int cnt = 0;
          int tmpSum = j;/*用tmpSum来代替j运算*/
          while(tmpSum){
             int x = tmpSum%2;
             tmp = x*Pow(10,cnt)+tmp;
             cnt++;
             tmpSum /= 2;
          }
          num[i][pos++] = tmp;
       }
    }
}

int main(){
   init();
   num[11][0] = 1e10;
   
   while(scanf("%d" , &n) != EOF){
     int ans = 0; 

     for(int i = 1 ; i <= 11 ; i++){
         if(n < num[i][0]){
           ans = vis[i-2];
           int j;
           
           for(j = 0 ; j < Pow(2 , i-2); j++){
              if(num[i-1][j] >= n){
                ans += j;
                if(num[i-1][j] == n)
                  ans++;
                break;
              }
           }
           if(j == Pow(2 , i-2))
             ans += Pow(2 , i-2);
           printf("%d\n" , ans);
           break;
         }
      }
   }
   return 0;
}


D

思路;dp

分析:

1 给定n和h表示n个节点和高度不低于h的二叉搜索树的个数

2 dp[i][j]表示i个节点最大高度为j的二叉搜索树的个数,枚举节点数i和高度j以及左子树的节点数k

dp[i][j] += dp[k][j-1]*dp[i-k-1][j];

3 初始化dp[0][i] = 1;

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long int64;
const int N = 40;

int n , h;
int64 dp[N][N]; 

void init(){
	for(int i = 0 ; i < N ; i++)
		dp[0][i] = 1;

	for(int i = 1 ; i < N ; i++)
		for(int j = 1 ; j < N ; j++)
			for(int k = 0 ; k < i ; k++)
				dp[i][j] += dp[k][j-1]*dp[i-k-1][j-1];
}

int main(){
	init();
	while(~scanf("%d%d" , &n , &h))
		cout<<(dp[n][n]-dp[n][h-1])<<endl;
	return 0;
}


E

思路:暴力+并查集

分析:

1 题目的意思是给定n个点和m条已知的边的无向图,要求添加最少的边使得这个无向图是一个interesting graph

2 题目定义interesting graph是指每个点只能属于某一个环,并且是一个funny ring。而funny ring则是一个环通过所有的点一次

3 经过1和2两点的分析,我们知道题目最后要求就是给定n个点和m条已知的边,使得添加最少的边得到一个funny ring。

4 求出每个点的度数,然后暴力枚举即可

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int N = 55;
const int MAXN = 2510;

int n , m;
int degree[N];
int father[N];

struct Edge{
	int x;
	int y;
};
Edge e[MAXN];

void init(){
	for(int i = 1 ; i <= n ; i++)
		father[i] = i;
}

int find(int x){
	if(x != father[x])
		father[x] = find(father[x]);
	return father[x];
}

bool unionSet(int x , int y , int ans){
	int fx = find(x);
	int fy = find(y);
	if(fx != fy){
		father[fx] = fy;
		return true;
	}
	return ans+m+1 == n;
}

bool check(){
	int root = find(1);
	for(int i = 1 ; i <= n ; i++)
		if(degree[i] != 2 || find(i) != root)
			return false;
	return true;
}

void solve(){
	if(n == 1){
		if(m == 0) printf("YES\n1\n1 1\n");
		else printf("YES\n0\n"); 
		return;
	}
	int ans = 0;

	for(int i = 1 ; i <= n ; i++){
		for(int j = 1 ; degree[i] < 2 && j <= n ; j++){
			if(i != j && degree[j] < 2){
				if(unionSet(i , j , ans) == false)
					continue;
				degree[i]++ ; degree[j]++;
				e[ans].x = i; e[ans++].y = j;
			}
		}
	}
	if(!check()){
		puts("NO");
		return;
	}
	puts("YES");
	printf("%d\n" , ans);
    for(int i = 0 ; i < ans ; i++)
		printf("%d %d\n" , min(e[i].x,e[i].y) , max(e[i].x , e[i].y));
}

int main(){
	bool isOk;
	int x , y;
	while(scanf("%d%d" , &n , &m) != EOF){
		isOk = true;
		init();
		memset(degree , 0 , sizeof(degree));
		for(int i = 0 ; i < m ; i++){
			scanf("%d%d" , &x , &y);
			if(x > y) swap(x , y);
			unionSet(x , y , 0);
			degree[x]++ ; degree[y]++;
			if(degree[x] > 2 || degree[y] > 2)
				isOk = false;
		}
		if(isOk)
			solve();
		else
			puts("NO");
	}
    return 0;
}



分享到:
评论

相关推荐

    Codeforces Round #723 (Div. 2).md

    Codeforces Round #723 (Div. 2).md

    Codeforces Round #630 (Div. 2) D. Walk on Matrix(构造)

    上面代码跑出来的dp[n][m]是0,然后从(1,1)(1,2)(2,2)(2,3)这样的相与值是k (看懂ans+k是啥应该就懂了) 代码: int main() { std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int ans=(1&...

    Codeforces Round #627 (Div. 3) C. Frog Jumps(思维)

    传送门 题意: 开始位置在0,问能否跳到n+1位置 每步只能跳d 在1——n每个位置有方向,L,R,求d的最小值 思路: 只用找相邻两个R之间的最大值即可 代码: #include #include ...typedef long long l

    Codeforces Round #627 (Div. 3) B. Yet Another Palindrome Problem

    就是把所有相等的数放到一个vector里,如果他出现大于2次,看最远的间距是否大于2即可,找到一个就可以 代码: #include #include #include #include #include #include #include #include #include #include #...

    Codeforces Round #629 (Div. 3) B. K-th Beautiful String

    长度为n的字符串包含n−2n−2n−2个aaa和222个bbb,求按照字典序排列输出第kkk个字符串 解题思路 第一个bbb在倒数第二位有1个字符串,在倒数第三位有2个字符串…在倒数第nnn位时有n−1n-1n−1个字符串 可以根据第一...

    Codeforces Round #629 (Div. 3) E.Tree Queries (DFS)

    Codeforces Round #629 (Div. 3) E.Tree Queries (DFS) 思路:若ai 在路径上 ,则ai的父结点一定在路径上,若ai是路径上某个结点的子结点,则ai的父结点一定在路径上,综上只需考虑ai的父节点就行了。对每个ai判断...

    Codeforces Round #479 (Div. 3) E. Cyclic Components

    E. Cyclic Components 题目链接-E. Cyclic Components 题目大意 给你nnn个点和mmm条边,求所构成图中单圈环的个数 ...并查集并查集并查集 很明显单圈环每个点的度都为222,所以我们可以用数组cnt[]记录每个点的度,...

    Codeforces Round #628 (Div. 2)

    给两两节点放一个数字(0~n-2 唯一) 给你一棵树,求所有任意两节点相连的路以外的路上的数字的最小值最小 思路 构造 若一个点连了三条边及以上,则这个点的边从最小值开始赋值。其他边从最大点开始赋值。 证明:一...

    Codeforces Round #620 (Div. 2) Longest Palindrome

    B. Longest Palindrome time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard output Returning back to problem solving, Gildong is now studying about ...

    Codeforces Round #628 (Div. 2) A. EhAb AnD gCd

    输入一个正整数x,找出这样的2个正整数a和b,使得gcd(a,b)+lcm(a,b)=x 解题思路 找最特殊的情况a=1,b=x-1即可 这样a,b两个数最大公因数为1,最小公倍数x-1,满足题意√ 附上代码 #include #define int long long #...

    Codeforces Round #635 (Div. 2)D. Xenia and Colorful Gems

    传说门 刚好今晚是中国场! 其实这道题比较水,但当时思路错,一心想着化简公式,浪费了好多时间a....#pragma GCC optimize(2) #include #define ll long long #define endl '\n' using namespace std; const int manx=

    Codeforces Round #628 (Div. 2) A~~D

    A #include using namespace std; typedef long long ll; int main(){ int t; cin&gt;&gt;t; while(t--){ ll x; cin&gt;&gt;x; cout&lt;&lt;1&gt;&gt;t; while(t--){ st.clear(); ll n; cin &gt;&gt;n;... ll re

    Codeforces Round #628 (Div. 2)【A B C D】

    传送门 A. EhAb AnD gCd 直接输出1,n-1即可 #include #include #include #include #include #include #include #include #include #include #define pb push_back #define lb lower_bound ...con

    Codeforces Round #633 (Div. 2) A. Filling Diamonds(找规律)

    传送门 题意: 找规律,题意就是有多少种方式填充该图形 画两个就发现,输出n即可 代码: #include #include #include #include #include #include #include #include ...#define SZ(x) ((int)(x)

    【Codeforces Round#620 (Div. 2)】B. Longest Palindrome 题解

    题目链接:B. Longest Palindrome 题目 Returning back to problem solving, Gildong is now studying about palindromes. He learned that a palindrome is a string that is the same as its reverse....

    Codeforces Round #627 (Div. 3) A. Yet Another Tetris Problem

    给一个长度为n的数组,两种操作,一个是把任意一个ai变成ai+2a_i变成a_i+2ai​变成ai​+2,另一个是如果所有数都大于0,可以把所有数减1,问通过这些操作能否把所有数变为0 思路: 如果任意两个数之差为奇数,那么就...

    Codeforces Round #633 (Div. 2) B. Sorted Adjacent Differences(排序,思维)

    -2,4,5,5,6,8 要输出的序列应该是每次从前面选一个,然后从后面选一个 -2,8,4,6,5,5 然后把该序列倒着输出即可 代码: #include #include #include #include #include #include #include #include #...

    Codeforces Round #618 (Div. 2) C. Anu Has a Function(进制,位运算,贪心)

    将所有数字看成2进制,从最高位看起,如果第i位上为1的数只有一个的话,那么这个数必然对答案有贡献,就把它排在第一个,后面任意排。 例:11,6,4,0 二进制表示为:1011,110,100,0 右起第四位为1的只有1011,...

Global site tag (gtag.js) - Google Analytics