点击打开链接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
上面代码跑出来的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&...
传送门 题意: 开始位置在0,问能否跳到n+1位置 每步只能跳d 在1——n每个位置有方向,L,R,求d的最小值 思路: 只用找相邻两个R之间的最大值即可 代码: #include #include ...typedef long long l
就是把所有相等的数放到一个vector里,如果他出现大于2次,看最远的间距是否大于2即可,找到一个就可以 代码: #include #include #include #include #include #include #include #include #include #include #...
长度为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) 思路:若ai 在路径上 ,则ai的父结点一定在路径上,若ai是路径上某个结点的子结点,则ai的父结点一定在路径上,综上只需考虑ai的父节点就行了。对每个ai判断...
E. Cyclic Components 题目链接-E. Cyclic Components 题目大意 给你nnn个点和mmm条边,求所构成图中单圈环的个数 ...并查集并查集并查集 很明显单圈环每个点的度都为222,所以我们可以用数组cnt[]记录每个点的度,...
给两两节点放一个数字(0~n-2 唯一) 给你一棵树,求所有任意两节点相连的路以外的路上的数字的最小值最小 思路 构造 若一个点连了三条边及以上,则这个点的边从最小值开始赋值。其他边从最大点开始赋值。 证明:一...
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 ...
输入一个正整数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 #...
传说门 刚好今晚是中国场! 其实这道题比较水,但当时思路错,一心想着化简公式,浪费了好多时间a....#pragma GCC optimize(2) #include #define ll long long #define endl '\n' using namespace std; const int manx=
A #include using namespace std; typedef long long ll; int main(){ int t; cin>>t; while(t--){ ll x; cin>>x; cout<<1>>t; while(t--){ st.clear(); ll n; cin >>n;... ll re
传送门 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
传送门 题意: 找规律,题意就是有多少种方式填充该图形 画两个就发现,输出n即可 代码: #include #include #include #include #include #include #include #include ...#define SZ(x) ((int)(x)
题目链接: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....
给一个长度为n的数组,两种操作,一个是把任意一个ai变成ai+2a_i变成a_i+2ai变成ai+2,另一个是如果所有数都大于0,可以把所有数减1,问通过这些操作能否把所有数变为0 思路: 如果任意两个数之差为奇数,那么就...
-2,4,5,5,6,8 要输出的序列应该是每次从前面选一个,然后从后面选一个 -2,8,4,6,5,5 然后把该序列倒着输出即可 代码: #include #include #include #include #include #include #include #include #...
将所有数字看成2进制,从最高位看起,如果第i位上为1的数只有一个的话,那么这个数必然对答案有贡献,就把它排在第一个,后面任意排。 例:11,6,4,0 二进制表示为:1011,110,100,0 右起第四位为1的只有1011,...