本次热身赛6道题目,由于没有官方解题报告,自己写了一个山寨版的解题报告,希望对学弟学妹有所帮助
期中两到签到题该校OJ上没有挂出,我在田大神的帮助下a掉了其它四题,解题报告如下所示
线段 | ||||||
| ||||||
Description | ||||||
坐标轴上有一些点,依次给出。点与点之间要求用一个半圆的直径连接,即把这两个点作为连接他们的半圆的直径的两个端点。第一个点与第二个点连,第二个与第三个连。半圆不能在坐标轴下面。问最后连出的图形,是否存在两个半圆他们是交叉的。 | ||||||
Input | ||||||
多组测试数据。 每组测试数据的第一行有一个数n(1 ≤ n ≤ 1000),表示有n个点。 之后一行有n个数x1, x2, ..., xn ( - 10^6 ≤ xi ≤ 10^6),每个数表示该点在坐标轴的位置。 | ||||||
Output | ||||||
如果最后的图形有交叉,输出yes,如果没有,输出no。 | ||||||
Sample Input | ||||||
4 0 10 5 15 4 0 15 5 10 | ||||||
Sample Output | ||||||
yes no | ||||||
Source | ||||||
2014.11.29新生赛-热身赛 |
要考虑多种情况,注意两个半圆有一点重合的地方那种情况就行
然后这题我用c++写的,如果要转化成c,只要把sort()排序函数,自己手写一个就行
就是按照x从小到大排序结构体,如果x1相同,按照从小到大排x2就行
比如数据0 15 5 10
排序后
0 15
5 10
5 15
然后每次往前比较,如有交叉的标记下
AC代码
- #include <iostream>
- #include <algorithm>
- #include <cstdio>
- using namespace std;
- const int maxn = 1e6+10;
- struct Node
- {
- int x,y;
- }node[maxn];
- bool cmp(Node a, Node b)
- {
- if(a.x == b.x) return a.y < b.y;
- return a.x < b.x;
- }
- int main()
- {
- int n;
- while(scanf("%d",&n) != EOF)
- {
- int a[1000];
- for(int i = 0; i < n; i++)
- {
- scanf("%d",&a[i]);
- }
- int cent = 0;
- for(int i = 1; i < n; i++)
- {
- node[cent].x = a[i-1] < a[i] ? a[i-1] : a[i];
- node[cent++].y = a[i-1] < a[i] ? a[i] : a[i-1];
- }
- sort(node,node+cent,cmp);
- int flag = 1;
- for(int i = 0; i < cent; i++)
- for(int j = 0; j < i; j++)
- {
- if( node[i].x == node[j].x && node[i].y >= node[j].y) continue;
- if(node[i].x < node[j].y && node[i].y > node[j].y)
- {
- flag = 0;
- }
- }
- if(flag) printf("no\n");
- else printf("yes\n");
- }
- return 0;
- }
组合 | ||||||
| ||||||
Description | ||||||
给出一个正整数N,从集合{1,2,3..N} 中找出所有大小为k的子集, 并按照字典序从小到大输出。 | ||||||
Input | ||||||
第一行是一个整数T,代表T组测试数据。 接下来T行,每行是两个正整数n(1<=n<=10), k(1<=k<=n)。 | ||||||
Output | ||||||
对于每组数据按字典序输出所有符合条件的子集。 | ||||||
Sample Input | ||||||
1 5 3 | ||||||
Sample Output | ||||||
1 2 3 1 2 4 1 2 5 1 3 4 1 3 5 1 4 5 2 3 4 2 3 5 2 4 5 3 4 5 | ||||||
Source | ||||||
2014.11.29新生赛-热身赛 |
这题用深搜解决,如果不会深搜就理解成不断的递归求解,自己最好拿样例手动在纸上面模拟一下代码就清楚了
- #include <stdio.h>
- #include <string.h>
- int a[11];
- int visit[11];
- int n,k;
- void dfs(int d, int q)
- {
- if(d == k)
- {
- printf("%d",a[0]);
- for(int i = 1; i < k; i++)
- printf(" %d",a[i]);
- printf("\n");
- return;
- }
- for(int i = q; i <= n; i++)
- {
- if(!visit[i])
- {
- visit[i] = 1;
- a[d] = i;
- dfs(d+1,i+1);
- visit[i] = 0;
- }
- }
- }
- int main()
- {
- int T;
- scanf("%d",&T);
- while(T--)
- {
- memset(a,0,sizeof(a));
- scanf("%d%d",&n,&k);
- dfs(0,1);
- }
- return 0;
- }
一个整数的正反面 | ||||||
| ||||||
Description | ||||||
给定一个整数n,和一个整数k。求比n小的,并且在k进制和 -k进制下表示出来的形式是一样的非负整数的个数,例如: 2 : 3进制下: 2 = 2*(30) , 所以2 用3进制表示的形式是2 -3 进制下: 2 = 2*(-3)0, 所以2 用-3 进制表示的形式是2 所以2 在 3 进制和-3进制下的形式是一样的。
再例如: 7: 3进制下: 7 = 1*(30) + 2*(31), 所以7用3进制表示的形式是21 -3进制下: 7 = 0*(-3)0+2*(-3)1+1*(-3)2,所以7用-3进制表示的形式是120 所以7在3进制和-3进制下的形式不一样。 p k进制:一个整数序列a0, a1, ..., ap,0 <= ai < |k| 并且 ∑(ai*ki)=x 。 i=0 | ||||||
Input | ||||||
每组输入包括一行,每行包括两个整数n和k。1 <= n <= 1e15, 2 <= k <= 1000。 | ||||||
Output | ||||||
每组输出包括一个整数,表示答案。 | ||||||
Sample Input | ||||||
21 3 21 2 | ||||||
Sample Output | ||||||
9 8 | ||||||
Hint | ||||||
第一组满足条件的非负整数:0 1 2 9 10 11 18 19 20 第二组满足条件的非负整数:0 1 4 5 16 17 20 21 | ||||||
Source | ||||||
2014.11.29新生赛-热身赛 |
这题是思维题目,要明白当所有的奇数位为0的时候才会满足要求
那如果求个数呢?
举个例子:
- #include <stdio.h>
- typedef long long LL;
- int a[65];
- LL n,k;
- int main()
- {
- while(scanf("%lld%lld",&n,&k) != EOF)
- {
- int len = 0,pos = 0,ans,pow;
- while(n)
- {
- a[len++] = n%k;
- n /= k;
- }
- for(int i = len-1; i >= 0; i--) //我们记录最高不为0的奇数位置
- {
- if(i%2 == 1 && a[i] != 0)
- {
- pos = i;
- break;
- }
- }
- for(int i = 0; i < pos; i += 2) //然后把pos之前的偶数位置全部置为k-1
- {
- a[i] = k-1;
- }
- ans = 0,pow = 1;
- for(int i = 0; i < len; i += 2)
- {
- ans += a[i]*pow;
- pow *= k;
- }
- printf("%d\n",ans+1);
- }
- return 0;
- }
无聊的小明 | ||||||
| ||||||
Description | ||||||
小明想用两个字母a和b创造一个长度为n的单词,但是他又不希望连续的a超过p个,同时也不希望连续的b超过q个。那么小明有能创造出多少个不用的单词呢? | ||||||
Input | ||||||
每组数据包括一行,三个整数n,p,q分别对应题意。 其中max(a, b) <= n <= 50000,1 <= a, b <= 300。 | ||||||
Output | ||||||
输出不同的单词的个数。个数要对1000000007取模。 | ||||||
Sample Input | ||||||
3 2 1 | ||||||
Sample Output | ||||||
4 | ||||||
Source | ||||||
2014.11.29新生赛-热身赛 |
dp[i][j]表示长度为i 结尾数是j 的方案数量
xxxxxxxxx100
xxxxxxxx1000
- #include <stdio.h>
- #include <string.h>
- const int N = 50005;
- const int mod = 1e9+7;
- int dp[N][2];
- int main()
- {
- int n,a,b;
- while(scanf("%d%d%d",&n,&a,&b)!=EOF)
- {
- memset(dp,0,sizeof(dp));
- dp[0][1]=1;
- dp[0][0]=1;
- for(int i=1;i<=n;i++)
- {
- for(int j=1;j<=i&&j<=a;j++)
- {
- dp[i][1]+=dp[i-j][0];
- dp[i][1]%=mod;
- }
- for(int j=1;j<=i&&j<=b;j++)
- {
- dp[i][0]+=dp[i-j][1];
- dp[i][0]%=mod;
- }
- }
- printf("%d\n",(dp[n][0]+dp[n][1])%mod);
- }
- return 0;
- }
http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblemVolume
第一个简单的计算机几何可以A掉,还有就是组合那题也可以递归求出,其它两题有兴趣可以看看