zoukankan      html  css  js  c++  java
  • 校内测试总结

    对前几天测试的总结

    T1:

    桶哥要买一些全家桶。他有a元钱,而每个桶要b元钱。他能不能买到c个桶?

    代码(没什么好解释的):

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int main(){
        long long a,b,c;
        scanf("%lld%lld%lld",&a,&b,&c);
        if(a>=b*c)
            printf("Yes
    ");
        else
            printf("No
    ");
        return 0;
    }

    然而当初只有90分,原因是无脑除法,完全忽略除数为0的情况,但如果用乘法的话,会因1018而爆int,需开long long,于是好多人只有九十分。。。

    T2:

    桶哥买了n个桶, 他要将这些桶送去n个人的家。他送第i个桶需要ai的时间,需要在bi之前送到。桶哥很懒,他想要尽量晚起身去送桶。问他最晚什么时候要去送桶?

    桶哥在送完一个桶之后可以紧接着去送另一个桶。

    当时的第一种思路:用最晚时间减去所需时长...

    20分...

    然后考虑到这种情况:

    如图(线段起点表示最晚送出时间(b-a),线段终点表示最晚接受时间),

    容易发现如果中间有一定空档,则后面的线段就无需考虑,

    再次改进算法

    60分(我已经不心疼AC率了)...

    再次找到一种情况:

    如图,显然此时的时间并不是b点减去时长2,因此前面提到过的算法全是错的

    那么换一种思路:

    设变量ti(设time会因与函数同名而报错)为答案,n(桶数)

    将变量ti初始化为最后一个桶的最晚接受时间,

    将每个桶按照最晚接受时间排序,然后倒序遍历,如果当前有未送的桶可以送,那么将ti减去该桶所用时间,剩余桶数自减

    如果没有桶可以送,那么将ti自减,直到遇到可以送的桶

    此算法可保证在正确数据与一定数据范围下算出正确答案

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    int n;
    struct ti{
        int a,b,c;
    }t[1000005];
    bool cmp(const ti &x,const ti &y){
        return x.b<y.b;
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d%d",&t[i].a,&t[i].b),t[i].c=t[i].b-t[i].a;
        sort(t+1,t+1+n,cmp);
        int time=t[n].b;
        while(n>0){
            if(time<=t[n].b){
                time-=t[n].a;
                n--;
            }
            else
                time--;
        }
        printf("%d
    ",time);
        return 0;
    }

    T3(最难的一道):

    桶哥的桶没有送完,他还有n个桶。他决定把这些桶吃掉。他的每一个桶两个属性:种类ai和美味值bi。若下标为x, y, z(下标从1开始)的三个桶满足:

    x < z 且 x + y = z - 2y 且 ax = az

    那么它们构成一个套餐,会产生

    (x + z) * (bx - bz)

    的价值。问:一共会产生多少价值?

    先分析题目

    现有n个桶,要找出满足搭配条件的组合并按照法则计算价值

    按照公式展开,即得:

    x*bx+z*bx-x*bz-z*bz

    可发现其实其价值与y没有任何关系,那么只要满足(z-x)%3=0就可以

    那么按照一定顺序枚举就可以计算每项对应值

    然而一个个枚举过于麻烦,于是可以只按照3的倍数进行枚举

    然后将其分为三组,分别按照%3的余数进行考虑,分为1,2,3,三组(其中一组%3为0,但下标为0无意义),分别以它作为起点开始遍历,每次自加3,保证“3的倍数”这一性质,

    又可以发现,在枚举z的过程中,也需处理前面的x,但是对于每一个z,前面的x可以以总和的形式参与计算,也就是说并无需枚举每一个x,只需将每一个z累加,在下一次循环枚举计算时,“曾经的z”作为x之和的一个元素出现,也就是每个z都将在后面的计算中当做x处理,这样保证只有与z有关的变量会导致当前值的不同,只需将x*bx以及只与x有关的变量当做一个会自动变化的常量,使其参与计算即可。

    但此种枚举可能出现种类(ai)不一致的情况,对于此,只需将x的和加上角标,其角标即为种类,也就是只有相同种类的桶可被累加在同一集合进行下面运算,

    另外,不要忘记取模

    代码(搬了下_rqy大佬的标程):

    #include <algorithm>
    #include <cctype>
    #include <cstdio>
    #include <cstring>
    int readInt() {
      int ans = 0, c, f = 1;
      while (!isdigit(c = getchar()))
        if (c == '-') f *= -1;
      do ans = ans * 10 + c - '0';
      while (isdigit(c = getchar()));     //声明:此函数用来看这个字符是不是数字,应该等价于ASCII码比较
      return ans * f;
    }
    //需要快读因为数据太多
    const int mod = 10007;
    
    int b[100005], a[100005];
    int S[100005], Sx[100005], Sbx[100005], Sxbx[100005];
    
    int main() {
      int n = readInt(),m = readInt();
      for(int i = 1; i <= n; i++) b[i] = readInt() % mod;
      for(int i = 1; i <= n; i++) a[i] = readInt();   //作为角标并不能模
      int ans = 0;
      for (int cc = 1; cc <= 3; ++cc) {
        // { cc, cc+3, cc+6 ... } 分一组
        memset(S, 0, sizeof(S));
        memset(Sx, 0, sizeof(Sx));
        memset(Sbx, 0, sizeof(Sbx));
        memset(Sxbx, 0, sizeof(Sxbx));
        for(int i = cc; i <= n; i += 3) {
          ans = (ans + i % mod * Sbx[a[i]] % mod) % mod;
          ans = (ans - b[i] * Sx[a[i]] % mod) % mod;
          ans = (ans + Sxbx[a[i]]) % mod;
          ans = (ans - S[a[i]] * b[i] % mod * (i % mod) % mod) % mod;
          S[a[i]] = (S[a[i]] + 1) % mod;
          Sx[a[i]] = (Sx[a[i]] + i) % mod;
          Sbx[a[i]] = (Sbx[a[i]] + b[i]) % mod;
          Sxbx[a[i]] = (Sxbx[a[i]] + i % mod * b[i] % mod) % mod;
        }
      }
      printf("%d", (ans + mod) % mod);   //处理负数情况
      return 0;
    }

    后面两题都是_rqy给的思路,_rqy好强呀%%%

    话说这位桶哥什么心情...

  • 相关阅读:
    IsPostBack
    多次点击Button后DropDownList选中的值变为默认值?
    数据表数据的复制
    使用DriverManager获取数据库连接
    通过Driver获取数据库连接
    URL学习笔记
    使用UDP进行数据发送的实例一
    利用Socket 客户端---->服务端 传送文件到指定路径,并返回一个友好的回馈
    关于TCP的两个小练习_第一个博客~
    oracle-19c-单实例安装-一键式脚本
  • 原文地址:https://www.cnblogs.com/648-233/p/10946039.html
Copyright © 2011-2022 走看看