USACO 1.5 Binary Numbers

26 篇文章 0 订阅

Notes

  • 把二进制数转化3或4个一组 表示为8(hex 0)或16(octal 0x)进制
  • bitwise 位运算符
  • shifting 位移

    • When shifting to the left, 0’s are inserted in the lower end.
      When shifting to the right, the high order bit is duplicated
      and inserted for the newly-needed bit (thus preserving the number’s sign).
      This means that (-1)>>1 yields -1 instead of 0!
ValueSampleMeaning
x00101100the original x value
x & -x00000100extract 取出 lowest bit set
x | -x11111100create mask for lowest-set-bit & bits to its left
x ^ -x11111000create mask bits to left of lowest bit set
x & (x-1)00101000strip off lowest bit set–> useful to process words in O(bits set)[instead of O(nbits in a word)]
x | (x-1)00101111fill in all bits below lowest bit set
x ^ (x-1)00000111create mask for lowest-set-bit & bits to its right
~x & (x-1)00000011create mask for bits to right of lowest bit set
x | (x+1)00101101toggle lowest zero bit
x / (x&-x)00001011shift number right so lowest set bit is at bit 0

数字三角形

  • 从上向下
    sum[i][j]=max(sum[i-1][j],sum[i-1][j-1])+nums[i][j];

  • 从下向上

for (i = 0; i < rows; i++)
    res[i] = tri[rows-1][i];
for (i = rows-1; i > 0; i--)
    for (j = 0; j <= i; j++)
      res[j] = tri[i-1][j] + max(res[j],res[j+1]);

pprimes*

本来想筛法暴力的..居然会超内存..打表算了= =
(希望打表不要被封号…

官方题解

  • Since there are only about 10,000 palindromes less than 100,000,000, we can just test each one to see if it is prime and in the range.(hint:回文数太少了,枚举回文数)
  • To generate a palindrome, we start with the first half and reverse it. The trick is that we can repeat the middle character or not repeat the middle character.(枚举一半即可)
  • The problem can be simplified slightly by noticing that any even palindrome is divisible by 11. Therefore, 11 is the ONLY even prime palindrome. This eliminates the need to deal with 2 cases(优化复杂度,任何偶数回文能被11整除)

整数的奇数位数字的和与偶数位数字的和之差,如果是11的倍数这数就是11的倍数,否则不是。

//枚举不同长度的
void generate(void){
    genoddeven(1, 9);
    genoddeven(10, 99);
    genoddeven(100, 999);
    genoddeven(1000, 9999);
}
/*
BTW 枚举量小的时候不用for循环结构会好看一些
*/
void genoddeven(int lo, int hi){
    int i;
    //奇数枚举
    for(i=lo; i<=hi; i++)
        gen(i, 1);
    //偶数枚举
    for(i=lo; i<=hi; i++)
        gen(i, 0);
}
void gen(int i, int isodd){
    char buf[30];
    char *p, *q;
    long n;
    //这里的枚举甚是奇妙
    //sprintf应该算是很快的tos()

    sprintf(buf, "%d", i);
    //p是最后一位+1
    p = buf+strlen(buf);
    /* 奇数: q 最后一位   的指针
       偶数: q 倒数第二位 的指针*/
    q = p - isodd;

    //q没有枚举到第一位时,p往后走,等于前面对称位置

    while(q > buf)
        *p++ = *--q;

    *p = '\0';

    //说好的没有toi函数呢= =
    n = atol(buf);
    if(a <= n && n <= b && isprime(n))
        fprintf(fout, "%ld\n", n);
}
//另一种生成回文数的方法.更加直接  </
int reverse2(int num, int middle) {
    int i, save=num, digit, combino = 1;
    for (i = 0; num; num /= 10) {
        digit = num % 10;
        i = 10 * i + digit;
        combino *= 10;
    }
    return i+10*combino*save+combino*middle;
}
//又一村(原代码简化版

void genPalind(int num, int add, int mulleft, int mulright){

/*
expects 4 parameters 
num     = 1,3,5,7   剩下需要生成的回文数长度
add     = 0         左右已经定型数字 如10001
mulleft = 10^(n-1)  左右间隔倍数(左数位)
mulright= 1         左右间隔倍数(右数位)

int main()
    genPalind(3, 0, 100, 1);
    genPalind(5, 0, 10000, 1);
    genPalind(7, 0, 1000000, 1);
void tryPalind(int)
    判断是否是在[a,b]内的素数
*/
  int i; //生成数

  if (num==2){
    for (i=0; i<10; i++)
      tryPalind(add+mulleft*i+mulright*i);
  }
  else if (num==1){
    for (i=0; i<10; i++)
      tryPalind(add+mulright*i);
  }
  else {
  //尝试少两位的回文数?
    for (i=0; i<10; i++)
      genPalind(num-2, add+i*mulleft+i*mulright, mulleft/10, nmulright*10);
  }

}

从左到右任何分割素数

recursive search

void dfs(int now,int num){
    if (num==n) 
        if (isprime(now)) 
            fout<<now<<endl;
    else if(isprime(now))
        for (int i=1; i<10; i+=2)
            dfs(now*10+i, num+1);

}

还是很好奇csdn的markdown编辑器应该如何愉快地玩耍

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值