2019西北工业大学程序设计创新实践基地春季选拔赛(重现赛) 部分题解
A.Chino with Geometry
Chino的数学很差,因此Cocoa非常担心。这一天,Cocoa准备教Chino学习圆与直线的位置关系。
众所周知,直线和圆有三种位置关系:相离、相切、相割,主要根据圆心到直线的距离来判定。 现在我们来看看作业吧:
圆A是以整点为圆心、正整数为半径的圆,整点分别是圆外一点以及轴上的一点,形成一条圆的割线(也就是和圆有两个交点)。现在Cocoa想要知道,的值是多少?
题目对于Chino来说太难啦,你能帮一帮Chino吗?
输入描述:
六个正整数x0, y0, r, x1, y1, y2
输出描述:
题目要求的答案,精确到整数
示例1
输入
2 2 1 3 1 2
输出
1
题解:数学题,推了好久太浪费时间,太菜了…
过点A对直线BC作垂线于O,连接AE AD AB, 直角三角形AEO和直角三角形AOB两组勾股定理联立就能得出BD*BE =(x1-x0) * (x1-x0)+(y1-y0) * (y1-y0)-r * r
AC代码:
#include<iostream>
using namespace std;
typedef long long ll;
int main()
{
ll x0,y0,r,x1,y1,y2;
cin>>x0>>y0>>r>>x1>>y1>>y2;
cout<<(x1-x0)*(x1-x0)+(y1-y0)*(y1-y0)-r*r<<endl;
return 0;
}
B.Chino with Repeater
Chino的数学很差,因此Cocoa非常担心。今天,Cocoa准备教Chino数数。
我们都知道人类的本质之一是复读机,而复读机就是复读别人说过的话。
现在有下面这段程序: #include <stdio.h> // 包含标准库的信息
main() // 定义名为main的函数,它不接受参数值
{ // main函数的语句都被括在花括号中
printf(“Hello, world!”); // main函数调用库函数printf以显示字符串序列
} 显然,它的功能是打印一行.
现在,Cocoa想要知道,如果一台复读机每次可以复读若干行(但不超过已有的行数),那么最少复读几次可以让消息记录达到行呢?
题目对Chino来说太难啦,你能帮一帮Chino吗?
输入描述:
一个正整数n
输出描述:
题目中要求的答案
示例1
输入
复制
9
输出
4
说明
1→2→3→6→9
题解:水题,找规律,从大到小找,如果n为奇数 n=n/2+1 n为偶数 n=n/2 直到n=1结束,记录次数就ok了。
AC代码:
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int mmax=1e6+10;
int main()
{
ll n,k;
cin>>n;
for(int i=1;i<1000;i++)
{
if(n==1)
{
k=i-1;
break;
}
if(n%2==0)
n/=2;
else
n=n/2+1;
}
cout<<k<<endl;
return 0;
}
D.Chino with Equation
题目描述
Chino的数学很差,因此Cocoa非常担心。今天,Cocoa要教Chino解不定方程。
众所周知,不定方程的解有0个或者若干个。
给出方程: X1+X2+…+Xm=n(1<=m<=n<=1e6)
Cocoa想知道这个不定方程的正整数解和非负整数解各有几个。
题目对Chino来说太难啦,你能帮一帮Chino吗?
输入描述:
两个正整数m, n
输出描述:
题目要求的答案,即正整数解的个数和非负整数解的个数 。由于答案可能会很大,你只需要输出答案 mod(109 + 7) 即可。
示例1
输入
4 7
输出
20 120
题解:组合数问题,搞明白就好做了
正整数解(都>0): m个位置,要求和=n, 他只会有n-1个数组合(因为最小值是1,所以最大不可能是n),只需要确定m-1个位置 剩余的1个数自然就确定。所以正整数解为C(n-1,m-1)
非负整数解(都>=0): m个位置可能是0,此时这个位置为空,这样就有n+m-1个数组合(1~n 加上 m-1个空位子) 只需要确定m-1个位置 剩余的1个数自然就确定。所以正整数解为C(n+m-1,m-1)
思路明白了看怎么解决,数据要2e6 求组合数有技巧,首先打个从1到2e6的阶乘,
利用逆元定理求出最后的解。(因为同余定理没有除法,的需要计算他的逆元,利用费马小定理,aa ^ (p-2)=1(mod p) gcd(a,p)=1 ),主要计算a^(p-2)
组合数公式C(n,m)=n!/(m!(n-m)!)
AC代码:
#include<iostream>
using namespace std;
typedef long long ll;
const int mmax=2000010;
const int mod=1e9+7;
ll mul[mmax];
void init()
{
mul[0]=1;
for(int i=1;i<=2000000;i++)
{
mul[i]=(mul[i-1]*i)%mod;
}
}
ll quick_mul(ll a,ll b)
{
ll temp=a%mod;
ll ans=1;
while(b)
{
if(b&1)
ans=(ans*temp)%mod;
temp=(temp*temp)%mod;
b>>=1;
}
return ans%mod;
}
ll ni(ll a, ll b)
{
return quick_mul(a,b-2)%mod;
}
ll c(ll n,ll m)
{
return (mul[n]*ni(mul[n-m]*mul[m]%mod,mod))%mod;
}
int main()
{
init();
ll m,n;
cin>>m>>n;
cout<<c(n-1,m-1)<<" "<<c(n+m-1,m-1)<<endl;
return 0;
}
F.Chino with Expectation
题目描述
Chino的数学很差,因此Cocoa非常担心。这一天,Cocoa准备教Chino学习数学期望。众所周知,数学期望就是所有可能的结果乘以概率,那么我们可以说的期望
定义非常简单,Chino也一下就学会了。现在是作业时间啦!
Cocoa在纸上写下个正整数,接下来Cocoa会进行次询问,每次询问形如“x,l,r ”,表示如果Cocoa把数列中的某个数加上x以后的期望。
题目对于Chino来说太难啦,你能帮一帮Chino吗?
输入描述:
第一行是两个正整数n, q;接下来一行是n个数ai,接下来q行每行三个数xi, li, ri,描述了一组询问
输出描述:
对于每组询问,给出相应的回答。你的答案会被认为是正确的,当且仅当你的答案是a,标准答案是b,并且|a−b|max(1,b)≤10−6|a−b|max(1,b)≤10−6
示例1
输入
5 3
1 2 3 4 5
1 2 3
2 1 4
4 3 5
输出
2.700000
2.900000
4.800000
题解:从l到r的和用前缀和表示,难点是那个数加x 。
分两种情况讨论(P表示L,R 的期望)
- x加到非 L , R 区间,(非区间/总长度 ) * L,R的期望
- x加到L , R 区间,(区间长度/总长度) * (L,R的期望 + x /区间长度)
把两个加起来就是答案
AC代码:
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const int mmax=1e6+10;
ll sum[mmax],a[mmax];
int main()
{
ll n,p;
scanf("%lld %lld",&n,&p);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+a[i];
for(int i=1;i<=p;i++)
{
ll x,l,r;
scanf("%lld %lld %lld",&x,&l,&r);
double ans=0,p1,p2;
double ans0=(sum[r]-sum[l-1])/(double)(r-l+1);
p1=(double)(r-l+1)/n;
p2=(double)(n-(r-l+1))/n;
ans=p2*ans0+p1*(ans0+((double)x/(r-l+1)));
//cout<<p2<<" "<<p1<<" "<<ans0<<endl;
printf("%.6lf\n",ans);
}
return 0;
}