A:简单的二分答案,二分面积就好,判断的时候看每个pie够分几个人,sum一下和来的人数判断。
由于这题没写过,这里附上rank1(90n)的代码,pi最好是acos(-1,0), 但他这里写的并不好,如果define的话,每次调用都要计算一次,直接写const double pi=acos(-1)。pi只手写3.1415926会出现精度问题,会WA。
#include
#include
#include
#include
#include
using namespace std;
#define pi acos(-1.0)
double v[10010];
int t,n,f,i;
int pd(double x)
{
int sum=0;
for(i=0;i=1e-6)
{
mid=l+(r-l)/2;
if(pd(mid)>=f)l=mid;
else r=mid;
}
printf("%.4lf\n",mid);
}
}
B:快速幂就好,或者找个循环节,计算量更小,循环节长度最多不超过10,因为状态有限。
这里附上本题一血的代码(rank2):
#include
using namespace std;
int func(int n)
{
int a=n;
int b=1;
while(a>0){
if(a%2==1){
b=b%10;
n=n%10;
b=b*n;
}
n=n%10;
n=n*n;
a=a>>1;
}
return b%10;
}
int main()
{
int t;
cin>>t;
int m;
while(t--){
cin>>m;
cout<
C:题目大意:有n条绳子,长度分别为L[i]。如果从他们中切割出k条长度相同的绳子的话,这k条绳子每条最长能有多长?
二分答案,二分想要的绳子长度,每二分一次o(n)算可以获得多少个这样的绳子,再和y做比较就好。
#include
#include
using namespace std;
typedef long long ll;
const int N=1e5+10;
const double EPS=1e-9;
double n[N];
int main(){
int x,y;
cin>>x>>y;
double maxn=0;
for(int i=1;i<=x;++i){
scanf("%lf",&n[i]);
maxn=max(maxn,n[i]);
}
double l=0,r=maxn;
int Cnt=1000;
while(Cnt--){
double mid=(l+r)/2;
int cnt=0;
for(int i=1;i<=x;++i)
cnt+=n[i]/mid;
if(cnt>=y)
l=mid;
else
r=mid;
}
printf("%.2lf\n",floor(l*100)/100);
}
D: 上次比赛原题嘛:(没A的暴露了没补题
#include
using namespace std;
typedef long long ll;
const int N=1e5+10;
double A[N],B[N];
int n;
double t;
double check(double x){
double ans=0;
for(int i=1;i<=n;++i){
if(B[i]+x<=0){
return t+1;
}
ans+=A[i]/(B[i]+x);
}
return ans;
}
int main(){
cin>>n>>t;
for(int i=1;i<=n;++i)scanf("%lf%lf",&A[i],&B[i]);
double l=-1<<30,r=1<<30;
for(int i=1;i<=1000;++i){
double mid=(l+r)/2;
if(check(mid)<=t)r=mid;
else l=mid;
}
printf("%.9lf\n",l);
}
E:询问一个数x的第k大因子。
我们有个想法,从1枚举到x,看他能整除那个数就像这样:
for(int i=1;i<=x;++i){
if(x%i==0){
//do something
}
}
对不起,复杂度o(n),当n>1e8是肯定超时,我们想到当x%i==0时,其实可以算出两个因数,一个是i,另一个是n/i,这样我们枚举到根号n就好了,复杂度是根号级别的,当x为1e15是,刚刚号不超过1e8,然后利用你喜欢的方式记录一下。
#include
using namespace std;
int main(){
long long x;
long long y;
scanf("%lld%lld",&x,&y);
set num;
for(long long i=1;i*i<=x;++i){
if(x%i==0){
num.insert(i);
num.insert(x/i);
}
}
set::iterator it=num.begin();
if(y>num.size()){
cout<<"-1";
return 0;
}
for(int i=1;i
F:题意:每门课最多翘两次,翘掉最大价值的两次课,求翘掉课的最大的价值。
这道题直接贪心就好,其实是在考察STL库的使用:这里我使用了优先队列。
把每一门课开一个优先队列,这样这个队列的头总是这一门学科的最大值,然后贪心就好。(一年前写的代码,比较丑)
#include
using namespace std;
char a[100][10];
int num=0;
int look(char b[]){
int i;
for(i=0;i>x;
while(x--){
num=0;
memset(a,0,sizeof(a));
int ans=0;
priority_queue q[100];
cin>>y;
char s[10];
while(y--){
cin>>s>>z;
q[look(s)].push(z);
}
for(int i=0;i
G:题意:一个序列抽两个值,算mod p意义下的最大值。
我们可以用双针法在复杂度o(n)的情况下算出,输入后从小到大排个序,让左指针在最左边,右指针在最右边,如果这两个和小于p,++l,并更新一下可能的答案,如果超过p,--r,再更新答案就好,这样是保证在两个数加起来不超过p时的最大值,还有一种情况,就是两个数加起来大于p但mod p后还是最大的,那么可能情况只能时最大和次大加。
一血(90n)代码:
#include
#include
#include
#include
#include
using namespace std;
int main()
{
long long int n,p,i,a[100010],l,r,zd;
while(~scanf("%lld%lld",&n,&p))
{
memset(a,0,sizeof(a));
for(i=0;i=p)a[i]%=p;
}
sort(a,a+n);
l=0;r=n-1;
zd=(a[n-1]+a[n-2])%p;
while(l=p)r--;
else
{
zd=max(zd,a[l]+a[r]);
l++;
}
}
printf("%lld\n",zd);
}
}
H:Announcement上解释数论的逆元,其实就是当a和M互质时,a相对于M的逆元就是pow(a,M-2),所以这道题其实是快速幂,当然后边学到数论还会有另一种解法,扩展欧几里得的解法,感兴趣的可以先自行百度。
一血代码( yuhao007):扩展欧几里得的做法
#include
int x,y;
void gcd(int a,int b)
{
int t;
if(b==0)
{
x=1;
y=0;
return;
}
else
{
gcd(b,a%b);
t=x;
x=y;
y=t-(a/b)*y;
}
}
main()
{
int T,n,m;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
gcd(m,9973);
if(x<0)
x+=9973;
x*=n;
printf("%d\n",x%9973);
}
return 0;
}
二血代码(90n):快速幂做法:
#include
#include
#include
#include
using namespace std;
typedef long long int lli;
lli ksm(lli b)
{
lli y=1,a=9971;
b=b%9973;
while(a)
{
if(a&1)y=(y*b)%9973;
b=b*b%9973;
a/=2;
}
return y;
}
int main()
{
int t;
lli a,b,f;
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld",&a,&b);
b=ksm(b);
f=a*b%9973;
printf("%lld\n",f);
}
}
I:是没有办法直接算阶乘的位数的,但是取个log,乘法不就是加法了,而log10表示的也恰好是位数:一血( chenghao2000324)的代码:
#include
#include
int main()
{
long n,p,t;scanf("%d",&t);
for(p=0;p
J: 水题不讲了
一血者(hheeeeee)的代码:
#include
int main()
{
int n;
int a[102]={0};
while(scanf("%d",&n)!=EOF)
{
int t=0;
for(int i=0;ia[i-1])
{
t+=(a[i]-a[i-1])*6;
}
else
{
t+=(a[i-1]-a[i])*4;
}
}
t+=5;
}
if(n==0)
{
break;
}
else
{
printf("%d\n",t);
}
}
return 0;
}
K: 折半枚举+HASH储存,防AK题,暴力枚举150^6肯定超时,我们可以这样,先暴力前一半150^3,记录到某种容器里,其实最方便的时map容器,但是复杂度多一个log,会超时,这里只能用hash table,然后再枚举后一半又是150^3,每次枚举完到容器里找到相加等于0的个数就好,这样复杂度150^3+150^3肯定不会超时,对这半枚举感兴趣的,了解一下2013年国家集训队论文集的《搜索问题中的 meet in the middle 技巧》江苏南京外国语学校 乔明达。
#include
#include