2016.8.8测试解题报告(binary,xx,minval,maxtrix)

来源:互联网 发布:行知实践园课程 编辑:程序博客网 时间:2024/05/21 06:35

呵呵,差点AK……今天下午的考试可谓不艰难,考完试之后我越发珍惜生命的美好了。

1.二进制除法

题目描述:
二进制数n mod m的结果是多少?

思路:
对于二进制数的取模运算,我们的第一反应一定是模拟其减法运算,然后逐位相减。但是这道题的数据达到了2e5,鉴于减法模拟的巨大常数,一定是会T的(这个我本人在考试的时候写了一个果然是T了不必感到任何的怀疑)。所以说我们换一个角度考虑这个问题——数论。看到取模我就想起来那个当年那个坑了我两个小时的取模分配率,然后我又注意到题目里那个比较小的数字,m的长度最大为20,仿佛一下就开启了新世界的大门,我可以先把m处理为10进制作为整个题的moder,然后用这个moder,一边用快速幂将n转为10进制一边取模,时间复杂度O(m+n)。

代码:

/*2016.8.8BulaBulaCHN*/#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<iostream>#include<iomanip>#include<cmath>#include<ctime>#include<algorithm>using namespace std;long long moder;long long p;long long tenbit;char x[200050];char y[50];int a1[200050];int a[200050];int main(){    freopen("binary.in","r",stdin);    freopen("binary.out","w",stdout);    scanf("%s%s",x,y);    int leny=strlen(y);    int lenx=strlen(x);    p=1;    for(int i=leny-1;i>=0;i--)    {        if(y[i]=='1') moder+=p;        p=p*2;    }//处理出moder    p=1;    for(int i=lenx-1;i>=0;i--)    {        if(x[i]=='1') tenbit=(tenbit+p);        tenbit%=moder;        p=(p*2);        p%=moder;    }//边取模边转十进制    while(1)    {        a1[++a1[0]]=tenbit%2;        tenbit/=2;        if(tenbit==0) break;    }//将结果转为二进制    if(!a1[0]) {cout<<0; return 0;}    for(int i=a1[0];i>=1;i--) cout<<a1[i];    fclose(stdin);    fclose(stdout);    return 0;}

2.奇怪的函数

题目描述:
使得x^x达到或超过n位数字的最小正整数x是多少?

思路:
其实第一眼看这个题的时候我是有一些畏惧的,因为这道题看起来根本就无从下手啊!
然而如果换到数学的角度,你把这句话从文字语言转为符号语言——log10(x^x)>=n,你就会发现可以导出这么一个公式x*log10(x)>=n。所以说这道题其实水得不行,只要二分出一个最小的满足条件的x就可以了。(注意用double控制一下精度)

代码:

/*2016.8.8BulaBulaCHN*/#include<cstdio>#include<cstdlib>#include<cmath>#include<algorithm>#include<string>#include<cstring>>#include<iostream>using namespace std;int n;int main(){    freopen("xx.in","r",stdin);    freopen("xx.out","w",stdout);    scanf("%d",&n);    int l=0,r=2000000000;    int mid;    while(l+1<r)    {        mid=(l+r)/2;        double lop=log10(mid)*mid;        if(lop>=n) r=mid;        else l=mid;    }    printf("%d",r);    fclose(stdin);    fclose(stdout);    return 0;}

3.最小函数值

题目描述:
有n个函数,分别为F1,F2,…,Fn。定义Fi(x)=Ai*x^2+Bi*x+Ci(x∈N*)。给定这些Ai、Bi和Ci,请求出所有函数的所有函数值中最小的m个(如有重复的要输出多个)。
Ai<=10,Bi<=100,Ci<=10 000。

思路:
唉……又是一道大水题。一看数据范围,就是一个在值域范围之内单调递增的函数,每一次枚举只要从0开始就可以了。我和正解都使用了堆的数据结构,每次生成一个函数值都放在堆里面,直到加入了m个元素为止。时间负责度严格的O(n)。

代码:

/*2016.8.8BulaBulaCHN*/#include<cstdio>#include<cstdlib>#include<cmath>#include<algorithm>#include<string>#include<cstring>#include<iostream>using namespace std;struct hanshu{       int val;       int num;       int v;       int x,y,z;};hanshu a[10001];int n,m;int vl(int a,int b,int c,int v){    return a*v*v+b*v+c;}void td(int i,int n){   int j;   while(i*2<=n)   {      j=2*i;      if(j+1<=n && a[j+1].val<a[j].val) j++;      if(a[i].val>a[j].val)      {          swap(a[i],a[j]);          i=j;      }      else break;   }   return;}//调堆函数int main(){    freopen("minval.in","r",stdin);    freopen("minval.out","w",stdout);    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)    {        scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);        a[i].v=1;        a[i].val=vl(a[i].x,a[i].y,a[i].z,a[i].v);        a[i].num=i;    }    for(int i=n/2;i>=1;i--) td(i,n);    int i=0;    while(1)    {        cout<<a[1].val<<" ";        a[1].v++;        a[1].val=vl(a[1].x,a[1].y,a[1].z,a[1].v);        td(1,n);        i++;        if(i==m) break;    }    return 0;}

4.矩阵乘法

题目描述:
一个A x B的矩阵乘以一个B x C的矩阵将得到一个A x C的矩阵,时间复杂度为A x B x C。矩阵乘法满足结合律(但不满足交换律)。顺序给出n个矩阵的大小,请问计算出它们的乘积的最少需要花费多少时间。

思路:
根据矩阵乘法的性质,我们可以得知,每一个矩阵的行数一定等于上一个矩阵的列数,于是我们可以压缩矩阵的存储状态:例如,输入数据为10 100、100 5、5 50时,我们可以将其压缩为10 100 5 50(想一想,为什么)。然后我们将对它们进行合并操作,大家看到这一定想起来那个经典的合并石堆的区间dp问题。很多人听我讲到这的第一反映就是“那就是枚举起点和重点了?”,其实并不是这样。由于一个大矩阵的形成一定来源于合并,要合并就要有小矩形(小区间),所以说要保证在枚举区间的时候保持区间内的元素都被都已经是最优值,就应该使用区间动规的经典套路:枚举区间长度、起点和断电(此处注意不要数组越界!)。所以讲到这我们很容易得出动态转移方程:
f[i][j]=max(f[i][j],f[i][k]+f[k][j]+a[i]*a[k]*a[j])
相信讲到这,所有人都知道要怎么实现了,接下来就是初始化等细节的问题了。

代码:

/*2016.8.8 BulaBulaCHN*/#include<cstdio>#include<cstdlib>#include<cmath>#include<algorithm>#include<string>#include<cstring>#include<iostream>using namespace std;int minn(int a,int b) {if(a<b) return a; return b;}int n;int a[105];int f[105][105];int main(){    for(int i=1;i<=105;i++)        for(int j=1;j<=105;j++)            f[i][j]=9999999;//为了更新最小值,初始化为最大值    freopen("matrix.in","r",stdin);    freopen("matrix.out","w",stdout);    scanf("%d",&n);    for(int i=1;i<=n;i++)    {        int x,y;        scanf("%d%d",&x,&y);        a[i]=x;        if(i==n) a[i+1]=y;//处理状态    }    n++;    int ed;    for(int i=1;i<=n;i++) f[i][i]=0,f[i][i+1]=0;    for(int len=2;len<=n-1;len++)        for(int st=1;st<=n;st++)            if(st+len<=n)//终点没有越界            {                ed=st+len;                for(int k=st+1;k<ed;k++)                f[st][ed]=min(f[st][ed],f[st][k]+f[k][ed]+a[st]*a[k]*a[ed]);            }    printf("%d",f[1][n]);//最终状态    fclose(stdin);    fclose(stdout);    return 0;}

今天的题都挺怪的,不过我已经感觉头疼欲裂了……

1 0
原创粉丝点击