Hdu 1496 Equations [hash]及memset效率分析

题目链接:点击打开链接

题目就是要求你四元二次方程的解数。

这道题,算是有点hash的味道了。

不多说,直接代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N=105;
const int H=1000000;
const int M=2000005;
int p[N],hash[M];
int main(){
    for(int i=1;i<=100;i++)
    p[i]=i*i;
    int a,b,c,d;
    while(~scanf("%d%d%d%d",&a,&b,&c,&d)){
        if((a>0&&b>0&&c>0&&d>0)||(a<0&&b<0&&c<0&&d<0)){
            printf("0\n");
            continue;
        }
        memset(hash,0,sizeof(hash));
        for(int i=1;i<=100;i++){
            for(int j=1;j<=100;j++)
            hash[a*p[i]+b*p[j]+H]++;
        }
        int cnt=0;
        for(int i=1;i<=100;i++){
            for(int j=1;j<=100;j++)
            cnt+=hash[-(c*p[i]+d*p[j])+H];
        }
        printf("%d\n",cnt*16);
    }
    return 0;
}

如果没有判断a,b,c,d是同号的话,会超时。

一直以为,memset的效率不是很高的吗。以前也听学长说过,memset的效率和普通的for循环差不多。然后就百度学习了一下。

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

以下转至其他博客:

void *memset(void *s, int ch, size_t n);
作用:将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值, 块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作。
不知道有没有像我一样把memset当作万能的初始化工具,例如:
int arr[n];
memset(arr,1,n*sizeof(int));
这样得到的arr数组一定不是全0,而是16843009,下面解释原因。
首先,变量类型的本质只是标志从某一内存地址开始读取的位数,强制转换就是改变读取位数的大小。

下面来看memset的实现:(代码来自《C标准库》P398)

  1. void *(memset) (void *s,int c,size_t n)  
  2. {  
  3.     const unsigned char uc = c;  
  4.     unsigned char *su;  
  5.     for(su = s;0 < n;++su,--n)  
  6.         *su = uc;  
  7.     return s;  
  8. }  
第3行把int类型的c转换成unsigned char类型,意味着截去c的高24位,只保留低8位。第4行把s当作unsigned char*类型,也就是说su中的每一个元素按8位计算。
现在来看看文章开头的那个代码会做什么。
c的二进制 : 00000000000000000000000000000001(32位)
1、c转换为unsigned char 后:00000001(8位)
2、将指针su(unsigned char类型)的每一元素(8位)赋值为00000001,循环4n次。
3、memset()结束后,arr的每个元素按照int类型读取,读出来的就是1000000010000000100000001,十进制就是16843009。

不过如果是memset(arr,0,n*sizeof(int));的话可以使用,因为32位都是0

再来说memset()的效率问题。使用memset函数与将上面的函数代码写在自己的程序里是不一样的,C标准库中的memset对Cache的利用做了优化,具体的在《C专家编程》151页有解释(其实是我没看懂),这里给出测试:
  1. #include <string.h>  
  2. #define MAXSIZE 100000  
  3.   
  4. int main()  
  5. {  
  6.     char arr[MAXSIZE];  
  7.     for(int i=0;i<10000;i++)  
  8.     {  
  9.         memset(arr,'0',sizeof(arr));  
  10. //        for(int j=0;j<MAXSIZE;j++)  
  11. //            arr[0] = '0';  
  12.     }  
  13.     return 0;  
  14. }  
程序里的注释部分与memset行分别使用,结果是使用memset的程序运行时间大约为0.1s,而用for循环的程序要3s多。
综上:memset()可以用在字符数组的初始化以及类似于memset(arr,0,n*sizeof(int));的情况,效率比手动赋值要高的多

-------------------------------------------------------------------------------------------------------------------

但是

比如 要全部赋值为-1。这个也是可以的吧。
1000 0000 0000 0000 000 0000 0000 0001。
去掉高24 ,0000 0001。这不是和1一样了吗???
但是 我们知道 -1 是可以赋值成功的。。。。。。。。。。

为什么呢?我有凌乱了。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值