2 条题解

  • 1
    @ 2024-8-3 21:00:58

    一种分治的写法

    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #define rep(x,a,b) for (int x=int(a);x<=(int)(b);x++)
    #define drp(x,a,b) for (int x=int(a);x>=(int)(b);x--)
    #define cross(x,a) for (int x=hd[a];~x;x=nx[x])
    #define ll long long
    using namespace std;
    ll x,y,n,ans,m,l,r;
    double xx,yy;
    /*int round_(double number)
    {
        return (number > 0.0) ? floor(number + 0.5) : ceil(number - 0.5);
    }手写round*/
    int main()
    {
    	freopen("film.in","r",stdin);
    	freopen("film.out","w",stdout);
        while (scanf("%lf%lf%lld",&xx,&yy,&n)!=EOF)
        {
            x=round(xx*10000),y=round(yy*10000);//?四舍五入 
            if (x!=100000)//判断是否为十分
            {
                x+=500;//消除精度问题,最坏的情况是x数值比较大 
                x*=n;//总投票数 
                //?总投票数必须要 
                if (x%10000==0) x-=10000;
                else x-=x%10000;
            }
            else x*=n;//十分没有误差,直接求出总票数 
            //处理精度
            l=0,r=100000000000;//二分边界定大点,放心不会超
            ans=0;//投票数 
            do 
            {
                m=(l+r)>>1;//非负整数等同于处于2 
                if (x+m*10000<((y+500)*(n+m))) ans=m,r=m;//每次加一分平均分下落肯定最快
                else l=m;
            }while (l+1<r);//好像我的二分不是很规范啊。。。
            if (xx<=yy) ans=0;//判断初始情况,这种情况不需要再投票了 
            printf("%lld\n",ans);//输出结果		
        }
        return 0; 
    }
    
    • 1
      @ 2024-8-3 20:50:34

      【试题分析】 N个可取1-10的整数的平均数四舍五入保留一位小数是A,现在要你再放上x个整数使平均数四舍五入保留一位小数降至B,给你X,Y,N,求x最小值。 这道题既然范围很大(n>1000000,T>10000),很明显就不能硬模拟,要数学推导。 我们既然要将平均数降至Y,那么肯定只有全放1才可以更好地降低平均数,否则把高的改成1肯定平均更小。 首先先忽略精度问题,列出算式,设仍要投x张票可以达到目的的话。 原先数的总和就是AN,而新的数总和为x,最后就一共有N+x个数。这些数平均数要小于等于B,那么算式就是

      两边乘N+x,因为都是正数,所以不用变号

      移项合并,得

      所以两边除1-B,得到以下式子(因为1-B恒负,所以变号)

      因为x为整数,所以ceil向上取整即可。

      现在讨论精度问题,最坏情况下,真实的平均数是A+0.0499999......(这样初始分数最大)最后目标是B+0.049999999......(同理,因为四舍五入,这样就可以达到平均数)。这种情况下,需要的投票次数比较多。 所以上式中的A要用输入值加上0.0499999......,B也同理。 这就是为什么1-B恒负而不会出现0的原因(本来就B≥1,加上0.0499999......后必定>1) 但是这题有坑,因为N个数中每个数都是整数,所以AN也是整数,必须先取整。 另外,0.49999999......中9的数目多了会当成0.05,少了不准,在这可以用12个9。 此外,A和B因为不可能超过10,所以都要对10取min。 再之后,A可能小于等于B,这时要回答0。 【参考代码】

      #include<bits/stdc++.h>
      #define LL long long 
      #define LD long double 
      LD a,b;
      LL n;
      int main()
      {
      	freopen("film.in","r",stdin);
      	freopen("film.out","w",stdout);
          while (scanf("%llf%llf%lld",&a,&b,&n)!=EOF)
          {
          	//如果a<=b,例如:2.0<=2.5,不需要再投票就已经满足条件 
              if(a<=b)
      	    {
      			printf("0\n");
      			continue;
      		}
      		a=a+(LD)0.04999999999999;//解决精度问题		
      		if(a>(LD)10.0) a=(LD)10.0;//A因为不可能超过10,所以都要对10取min
      		//a=min((LD)10.0,a);
      		b=b+(LD)0.04999999999999;
      		if(b>(LD)10.0) b=(LD)10.0;//B因为不可能超过10,所以都要对10取min
      		//b=min((LD)10.0,b);
      		
      		int f=a*n;//AN也是整数,必须先取整 
      		LD d=((LD)(b*n-f)/((LD)1-b));//根据公式求解 
      		printf("%lld\n",(LL)ceil(d));//
          }
      }
      
      • @ 2024-8-3 21:09:20

        真的需要辣么高de精度么?

        #include<cstdio>
        #include<cmath>
        using namespace std;
        
        double const DEBUG=0.05-pow(10, -10);
        
        int main(){
            double now, exp;
        	int n;
        	while(scanf("%lf%lf%d", &now, &exp, &n) == 3){
        		now = fmin(10, now+DEBUG);
        		exp = fmin(10, exp+DEBUG);
        		
        		int sum=now*n;
        		
        		double x=(exp*n-sum)/(1.0-exp);
        		printf("%.0lf\n", fmax(ceil(x), 0));
        	} 
        
            return 0;
        }
        
    • 1

    信息

    ID
    1366
    时间
    1000ms
    内存
    256MiB
    难度
    8
    标签
    递交数
    49
    已通过
    6
    上传者