====题目来自code.bupt.edu.cn======
A. 学姐的桌面 2014新生暑假个人排位赛01
题目描述
学姐在加入集训队之后,学习了使用ubuntu系统来做题,但是没有了360电脑管家,学姐再也没办法看到她的飞速电脑开机到底虐了全国多少人。作为一个电脑高手,学姐花了几分钟黑到了360的数据库拿到了全国360用户的开机时间,现在学姐想自己算算到底打败了百分之多少的人?
输入格式
输入有多组数据。首先给出数据组数 T(T≤10) ,下面 T 组数据,每组开头为 n(1≤n≤100000) ,360的用户数,和 t ,学姐的开机时间,接下来 n 个数字, ti 代表第 i 个用户的开机时间。其中 t , ti 为非负整数且小于 109 。
输出格式
每组数据一行,输出学姐打败了全国百分之多少的用户,精确到
签到题
整数比较大小
代码略
--------------------------------------------------------------------------------------------------------------------------------------------
B. 学姐去学车 2014新生暑假个人排位赛01
题目描述
趁着放假,学姐去学车好带学弟去兜风。但是学车真的很辛苦,每天五点半就要起床赶班车,但是学姐的教练更辛苦,他们要相同的时间到而且日日如此。于是温柔的学姐关切的问了他们的休息情况,教练告诉她,他们两个人倒班教学姐,每个教练每上 n 天班就会放一天假,如果一个教练放假,就由另一个教练来代课,一直代课到自己放假再换人。 现在学姐想知道,每一天是哪个教练给她上课。
输入格式
输入开始为数据组数 T(T≤10) ,接下来 T 组输入,第一行为 n,m ,我们假设第一天教学姐的是教练1,而且他教学姐的前一天刚刚放完假,教练2则会在学姐上课的第 m 天放假, 1≤m≤n 以保证每天都有教练教学姐。接下一行为 q(q≤103) ,即询问次数,接着 q 行,每行 ti 表示学姐想问哪天的教练是谁。因为教练们非常非常厉害,而且学姐不知道自己到底会花多久学完车,你的程序要处理的 n,m,ti 上限为 109 。
输出格式
对于每个询问 ti ,输出一行,1或2代表当天的教练。
输入样例
1
5 3
3
6
9
13
输出样例
2
1
2
水题 坑题 题意难懂 开始读不懂题交了个wa
思想就是找规律划分循环节
详见代码
#include <iostream>
#include <cstdio>
using namespace std;
int t,n,m,temp,q;
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
scanf("%d",&q);
while(q--)
{
scanf("%d",&temp);
if(temp<=n) {printf("1\n");continue;}
temp=(temp-n)%(n+1);
if(temp<=m && temp>=1) printf("2\n");
else printf("1\n");
}
}
return 0;
}
-------------------------------------------------------------------------------------------------------------------------------------------
C. 学姐的学弟 2014新生暑假个人排位赛01
题目描述
学姐正在写作业,但是她写着写着就开始想学弟,走神的她就开始在纸上画圈圈。这时学弟突然出现了,好奇的学弟问学姐在做什么,惊慌之下,学姐随口说想算一下这些圆覆盖的面积为多少。学弟顿时非常仰慕学姐,但是学姐突然意识到自己不会做,为了自己能给学弟留下好印象,她来求助你帮她算出来这些圆覆盖的面积。
为了简化问题,我们假设所有圆的半径都为1。
输入格式
输入有多组数据。开头为一个整数 T(T≤10) ,表示数据组数,接下来T组输入,每组开头为一个整数 n(1≤n≤100) ,表示学姐画的圆的个数,接下来 n 行,每行两个整数 xi,yi ,表示圆的圆心坐标, 1≤xi,yi≤100 。
输出格式
输出一个数,表示面积并,精确到小数点后五位。
输入样例
1
2
1 1
2 1
输出样例
5.05482
计算几何题
真的好麻烦好费时间T.T
个人代码比较挫,按从左到右从上到下的顺序加入圆
每加入一个,就加上圆的面积 同时减去和之前加过的重叠的面积
派的定义我用的4*atan(1),比较精确
注意最好把能用到的重叠的部分圆面积先define一下
define时式子要加括号哈
神犇学长们累加每个1乘1的小方格做的目测比较简单不用算这么多圆的碎片面积0.0
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define PI (4*atan(1))
#define zuida ((2*PI/3)-sqrt(3)/2)
#define cida (PI/2-1)
#define bianyuan (5*PI/12-sqrt(3)/2)
#define sancha ( 2*(5*PI/12-sqrt(3)/2)-(PI/3-sqrt(3)+1) )
using namespace std;
bool table[105][105];
int t,n;
double ans;
int main()
{
scanf("%d",&t);
while(t--)
{
memset(table,false,sizeof(table));
ans=0;
scanf("%d",&n);
while(n--)
{
int x,y;
scanf("%d%d",&x,&y);
table[x][y]=true;
}
for(int i=1;i<=100;i++)
for(int j=1;j<=100;j++)
if(table[i][j])
{
if(table[i-1][j-1])
{
if(table[i-1][j])
{
if(table[i-1][j+1])//111
{
if(table[i][j-1]) //zuida //jiaoxiao //bianyuan
ans+=PI-( zuida + 2*(cida) - 2*(bianyuan) +zuida -sancha);
else
ans+=PI-( zuida + 2*(cida) - 2*(bianyuan) );
}
else//110
{
if(table[i][j-1])
ans+=PI-( zuida + cida - (bianyuan) +zuida -sancha );
else
ans+=PI-( zuida + cida - (bianyuan) );
}
}
else
{
if(table[i-1][j+1])//101
{
if(table[i][j-1])
ans+=PI-( 2*(cida) +zuida -bianyuan );
else ans+=PI-( 2*(cida) );
}
else//100
{
if(table[i][j-1])
ans+=PI-( cida + zuida - bianyuan);
else ans+=PI-( cida );
}
}
}
else
{
if(table[i-1][j])
{
if(table[i-1][j+1])//011
{
if(table[i][j-1])
ans+=PI-( zuida + cida - (bianyuan) + zuida - (bianyuan) );
else
ans+=PI-( zuida + cida - (bianyuan) );
}
else//010
{
if(table[i][j-1])
ans+=PI-( zuida + zuida - (bianyuan) );
else ans+=PI-( zuida );
}
}
else
{
if(table[i-1][j+1])//001
{
if(table[i][j-1])
ans+=PI-( (cida) + zuida );
else
ans+=PI-( (cida) );
}
else//000
{
if(table[i][j-1])
ans+=PI - (zuida);
else ans+=PI;
}
}
}
}
printf("%.5lf\n",ans);
}
return 0;
}
----------------------------------------------------------------------------------------------------------------------------------
D. BLOCKS 2014新生暑假个人排位赛01
题目描述
给定一个 N∗M 的矩阵,求问里面有多少个由'#'组成的矩形,"There are 5 ships.",若是里面有一个不是矩形的联通块,则输出"So Sad"
输入格式
1≤n,m≤1000
有多组数据,EOF结束。
输出格式
每行对应一个answer
输入样例
6 8
.....#.#
##.....#
##.....#
.......#
#......#
#..#...#
6 8
.....#.#
##.....#
###...##
.......#
##.....#
#..#...#
输出样例
There are 5 ships.
So Sad
#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 1005
using namespace std;
char a[maxn][maxn];
int n,m,ans;
bool flag;
bool pd()
{
for(int i=2;i<=n;i++)
for(int j=2;j<=m;j++)
{
int tempsum=0;
if(a[i][j]=='.') tempsum++;
if(a[i][j-1]=='.') tempsum++;
if(a[i-1][j]=='.') tempsum++;
if(a[i-1][j-1]=='.') tempsum++;
if(tempsum==1) return false;
}
return true;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;i++) scanf("%s",a[i]);
for(int i=1;i<=n;i++)
for(int j=m;j>=1;j--)
a[i][j]=a[i][j-1];
for(int i=0;i<=max(m,n);i++) {a[0][i]='.';a[i][0]='.';}
if(!pd()) printf("So Sad\n");
else
{
ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(a[i][j]=='#' && a[i][j-1]=='.' && a[i-1][j]=='.') ans++;
printf("There are %d ships.\n",ans);
}
}
return 0;
}
------------------------------------------------------------------------------------------------------------------------------------------
E. 数的关系 2014新生暑假个人排位赛01
题目描述
用关系“<”和“=”将3个数A、B和C依序排列时有13种不同的序关系:
A=B=C,A=B<C,A<B=C,A<B<C,A<C<B,A=C<B,B<A=C,
B<A<C,B<C<A,B=C<A,C<A=B,C<A<B,C<B<A 。
现在输入数字的个数,要求你给出上述关系的数目。
数的个数不大于100
输入格式
多组数据,EOF结束
每行一个输入
输出格式
对于每个输入,输出一行,即对应答案
输入样例
3
输出样例
13
组合数学实在蒟蒻。。
比赛后请教了萌萌的黄学姐【ym】,终于会了
如果n个数,用m个小于号和n-m-1个等于号链接起来
等价于把n个不同的小球放入m+1个不同的盒子里,不许有空盒
(这个问题怎么解决,萌萌的黄学姐于是说,用dp)
设dp[i][j]表示把n个球放入m个盒中
考虑放最后一个球的过程,放之前如果有m-1个盒子,就是要加一个放1个球的盒子
插空呗,m-1个盒子算两侧,有m个空
如果放之前有m个盒子,就是把这个球放入任意一个中,有m种
所以dp[i][j]=dp[i-1][j-1]*j+dp[i-1][j]*j;
最后枚举等于号的个数,累加相应dp值就行嘞
这题得高精度,用java的biginteger写~
import java.io.*;
import java.math.*;
import java.util.*;
import java.text.*;
public class Main {
public static void main(String[] args)
{
Scanner cin = new Scanner (new BufferedInputStream(System.in));
int n,i,j;
BigInteger ans,temp1,temp2;
BigInteger dp[][]=new BigInteger[105][105];
for(i=1;i<=100;i++) dp[i][1]=BigInteger.ONE;
for(j=2;j<=100;j++) dp[1][j]=BigInteger.ZERO;
for(i=2;i<=100;i++)
for(j=2;j<=100;j++)
dp[i][j]=(dp[i-1][j-1].add(dp[i-1][j])).multiply(BigInteger.valueOf(j));
while(cin.hasNext())
{
n=cin.nextInt();
ans=BigInteger.ZERO;
for(i=1;i<=n;i++)
ans= ans.add(dp[n][i]);
System.out.println(ans);
}
}
}
--------------------------------------------------
最后附上一道题,和上题一样也是组合数学用dp解得,用来加深印象~。【思路是黄学姐的,再ym。】
D. Bricks 2014新生热身赛2
题目描述
There're many bricks with different heights put down on a straight line. When looking from one side, there're only some of them that could be viewed. More specifically, we cannot get a sight of a lower brick behind a higher one. For example, if we have 5 bricks with heights below: 3 5 2 9 8 then we can only see the bricks with heights of 3, 5 and 9 when we take a sight from the left side. Similarly, when we take a view from the right side, we can only see the bricks with height 8 and 9, where the other three bricks are blocked from our line of sight. Now you're given N bricks. The only limit comes out that we can only see L bricks when taking the view from left side, and R bricks from the right. Calculate how many ways we can put down the bricks to achieve it.输入格式
An integer T(T≤10) will exist in the first line of input, indicating the number of test cases. Each test case consists of one line with three integers N,L and R(1≤N≤5000,1≤L,R≤N) .输出格式
Since the answer could be large, you're only required to output the answer modulo 109+7 .输入样例
1
5 3 2
输出样例
18
最高的一根棍一定能被看见,我们以这根棍为界把所有的棍分成左右两部分
先从剩下的的n-1根棍中选出i根棍放到左面,其余放到右边,有C[n-1][i]种
左面的i根棍中,有l-1根可以被看见
设i根棍排在一起,有j根棍能被看见为dp[i][j]
每次都放入最小的棍的话,
dp[i][j]=dp[i-1][j-1] + dp[i-1][j]*(i-1);
//最小棍放入后能被看见,在最前面 //最小棍插到其余棍中间或所有棍的最后面,不能被看见
右面的n-i-1根棍同理,可以用一个dp方程
C和dp数组要预处理出来
求结果的过程见代码,求之前要if判断一下这种情况能否出现
还有,这题如果数组全开longlong,会mle
我们可以全开int,在转换时先用longlong存中间结果,再换回来
上ac代码
#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 5005
#define mo 1000000007
using namespace std;
int t,n,l,r;
int C[maxn][maxn];
int dp[maxn][maxn];
void MakeC()
{
C[0][0]=1;
for(int i=1;i<=5000;i++)
{
C[i][0]=1;
C[i][i]=1;
}
for(int i=2;i<=5000;i++)
for(int j=1;j<i;j++)
{
long long temp=((long long)C[i-1][j-1]+(long long)C[i-1][j])%mo;
C[i][j]=(int)temp;
}
}
void Makedp()
{
dp[0][0]=1;
for(int i=1;i<=5000;i++)
{
dp[i][i]=1;
dp[i][0]=0;
}
for(int i=2;i<=5000;i++)
for(int j=1;j<i;j++)
{
long long temp=((long long)dp[i-1][j-1]+(long long)dp[i-1][j]*(i-1))%mo;
dp[i][j]=(int)temp;
}
}
int main()
{
memset(C,0,sizeof(C));
memset(dp,0,sizeof(dp));
MakeC();
Makedp();
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&l,&r);
if(l+r>n+1) {printf("0\n");continue;}
int ans=0;
for(int i=0;i<=n-1;i++)
if(i>=l-1 && n-i-1>=r-1)
{
long long temp;
if(dp[i][l-1]<0) printf("aaaaa");
temp=((long long)C[n-1][i]*(long long)dp[i][l-1]%mo)*(long long)dp[n-i-1][r-1]%mo;
if(temp<0) printf("wwww");
ans+=(int)temp;
ans%=mo;
}
printf("%d\n",ans);
}
return 0;
}
============EOF===========