新普金娱乐网址


个人成长报告

常备问题总 一

bzoj1411: [ZJOI2009]硬币游戏

  • 十月 18, 2018
  • 数学
  • 没有评论

 5.1 二向前制插入

1411: [ZJOI2009]硬币游戏

Time Limit: 10 Sec  Memory
Limit: 162 MB
Submit: 965  Solved: 420
[Submit][Status][Discuss]

来一定量独32各项整数n和m,请编写算法将m的老二前进制数各插入到n的二进制的第j到第i个,其中二进制的位数从低数届高位且以0开始。

Description

Orez很喜欢玩游戏,他最近表明了一致放缓硬币游戏。他当台的边缘上分出2*n个位置并依照顺时针把它标号为1,2,……,2n,然后将n个硬币在标号为奇数的职位及。接下来每次按如下操作:在随心所欲两单硬币里放上一个硬币,然后用本的硬币拿走;所加大硬币的正反面由它们两边的片单硬币决定,若两只硬币均为方正朝上还是反面朝及,则所推广硬币为正直朝上,否则也反面朝及。
那么操作T次后桌子边缘上硬币的景况会是怎的呢?

叫一定两只数int n和int m,同时让定int j和int i,意义如题所述,请回来操作后的数,保证n的第j到第i各项都为零星,且m的二进制位数仅次于等于i-j+1。

Input

文件的首先履行包含两只整数n和T。
接下之同一实施包含n个整数,表示无比开始桌面边缘之硬币摆放情况,第i单整数ai表示第i单硬币摆放在2*i-1独岗位上,ai=1表示尊重朝及,ai=2表示反面朝及。

测试样例:

Output

文本就包含一行,为2n独整数,其中第i个整数bi桌面边缘之第i单职位上硬币的气象,bi=1表示尊重朝及,bi=2代表反面朝上,bi=0表示并未硬币。

1024,19,2,6

返回:1100

Sample Input

10 5
2 2 2 1 1 1 1 1 1 2

 画图——》移位+或

Sample Output

0 1 0 1 0 1 0 1 0 2 0 1 0 2 0 1 0 1 0 1

数码范围
30%的数据 n≤1000 T≤1000
100%的数据 n≤100000 T≤2^60

 

题解:转自http://blog.csdn.net/PoPoQQQ/article/details/39934161?locationNum=6

首先我们叫硬币正面为0 反面为1 那么好爱发觉新硬币的价为零星边硬币的异或值
样例也就是颇好讲了

1-1-1-0-0-0-0-0-0-1-   0
-0-0-1-0-0-0-0-0-1-0   1
0-0-1-1-0-0-0-0-1-1-   2
-0-1-0-1-0-0-0-1-0-1   3
1-1-1-1-1-0-0-1-1-1-   4
-0-0-0-0-1-0-1-0-0-0   5

接下来随即书n<=10W 矩阵乘法一定MLE 即使矩阵特殊结构可以提到少一维空间复杂度
O(n^2*logT)的年华呢无能为力承受

俺们仅考虑偶数的行

易知第二实行每个数是原列该位置左右个别只数的异或

出于数学归纳法可以
第2^k行每个数是原本列该位置左侧第2^(k-1)个数与右手第2^(k-1)个数的异或

下一场以T进行二进制拆分,每位进行同样不好变即可 最后更讨论T的奇偶

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring>
 6 #define ll long long
 7 
 8 using namespace std;
 9 
10 ll n,t,a[200000],b[200000];
11 ll f(ll b,ll k)
12 {
13     ll x=b-k,y=b+k;
14     x=(x%(n*2)+n*2-1)%(n*2)+1;
15     y=(y-1)%(n*2)+1;
16     if (k==0) return a[x];
17     if (a[x]==0) return 0;
18     if (a[x]==a[y]) return 1;
19     else return 2;
20 }
21 void work(ll k,ll q)
22 {
23     if (k==0) return;
24     work(k/2,q*2);
25     if (k%2==1)
26     {
27         memset(b,0,sizeof(b));
28         for (ll j=1;j<=n*2;j++)
29             b[j]=f(j,q);    
30         swap(a,b);
31     }
32 }
33 int main()
34 {
35     scanf("%lld%lld",&n,&t);
36     for (ll i=1;i<=n;i++)
37         scanf("%lld",&a[i*2-1]);
38 
39     work(t,1);
40 
41     for (ll i=1;i<n*2;i++)
42         printf("%d ",a[i]);
43     printf("%lld\n",a[n*2]);
44 }

 

import java.util.*;

public class BinInsert {
    public int binInsert(int n, int m, int j, int i) {
        return n|(m<<j);
    }
}

 

5.2 二进制小数

起一个介于0和1以内的实数,类型为double,返回她的二进制表示。如果该数字无法准确地用32号中的二进制表示,返回“Error”。

叫一定一个double num,表示0到1的实数,请返回一个string,代表该数的二进制表示还是“Error”。

测试样例:

0.625

返回:0.101

遵照在二进制和十进制小数的数学关系举行就是是了:乘2以及1比较

import java.util.*;

public class BinDecimal {
    public String printBin(double num) {
        StringBuffer res=new StringBuffer();
        res.append("0");
        res.append(".");
        for(int i=0;i<33;i++) {
            if(i==32) return "Error";
            num=num*2;
            if(num-1==0){
                res.append("1");
                break;
            }else if(num-1>0){
                res.append("1");
                num=num-1;
            }else{
                res.append("0");
            }
        }
        return res.toString();
    }
}

 

 当然,有时光可试试和0.5之类的举行减法;思路差不多

 

5.3 最相近的勤

蛮力法都还没有做下,等头脑清醒一点重新举行;

 

5.4 ((n&(n-1))==0)的含义

 从突出到一般重复届特种:A&B==0

 

5.5 整数转化

编制一个函数,确定要变更几乎只各类,才能够拿整数A转变成为整数B。

吃得两单整数int A,int B。请返回需要变更之数位个数。

测试样例:

10,5

返回:4

计数就好,注意用while

import java.util.*;

public class Transform {
    public int calcCost(int A, int B) {
        // 直接的思路,直接干,然后计数就好了嘛
        int count=0;
        int index=0;
        if (A==B) return count;
        while (A!=B) {
            if((A&(1<<index))!=(B&(1<<index))){
                count++;
                A=A^(1<<index);
            }
            index++;
        }
        return count;
    }
}

 

细节:用num^(1<<index)来改有一样各项的值;

 

5.6 奇偶位交换

请编写程序交换一个屡屡之二进制的奇数员以及偶数员。(使用越少的指令越好)

受得一个int x,请回交换后的数int。

测试样例:

10

返回:5

import java.util.*;

public class Exchange {
    public int exchangeOddEven(int x) {
        // 首先,实现功能,就是从头开始,两位两位的跳
        //问题在于如何判断结束,不如再弄一个数字,慢慢赋值
        int[] tmp=new int[2];
        //int y=0;
        //int res=0;
        int index=0;
       // int slow=0;
        tmp[0]=x;tmp[1]=0;
        while(x!=tmp[1]){
            swap(tmp,index);
            index=index+2;
        }

        return tmp[0];
    }

    void swap(int[] tmp,int index) {
        int first=0;
        int second=0;
        int xx=tmp[0];
        //int yy=tmp[1];

        first=xx&(1<<index);
        second=xx&(1<<(index+1));
        if (first!=0) first=1;
        if (second!=0) second=1;

        //先清零再置位
        tmp[0]=(tmp[0]&(~(1<<index)))|(second<<index);
        tmp[0]=(tmp[0]&(~(1<<(index+1))))|(first<<(index+1));

        //更新y
        tmp[1]=(tmp[1]|(first<<index))|(second<<(index+1));       


    }
}

 

 最主要点在于while的平息条件吧,对于自而言;

高超方法:先对拥有奇数位操作,再是偶数号,再要一下

return (((x & 0xaaaaaaaa)>>1)) | (((x & 0x55555555)<<1));

 

 

5.7 找来缺乏失的整数

数组A包含了0到n的有所整数,但内部缺失了一个。对于这题目,我们设定限制,使得一样不良操作无法取数组number里某个整数的总体内容。唯一的可用操作是询问数组中第i独元素的二进制的第j位(最低位也第0号),该操作的年华复杂度为常数,请设计算法,在O(n)的年月内找到这个数。

吃得一个数组number,即具备盈余的勤以自小到深排列的二进制各位的值,如A[0][1]表示剩下的次只数亚进制从没有及大的亚各。同时为得一个int n,意义如题。请回来缺失之频繁。

测试样例:

[[0],[0,1]]

返回:1

没意思。。不做。。

遵书及之思绪:一般的凡一体加以起来,少那个不畏是可怜;

这吧,就奇偶缺失来做就行!!!

 

总结

5.3
和5.8无搞定,5.7休思做,其他做了了,对各项运算,还是纯是率先各之,思路使活些,什么快慢指针,递归,数组,字符串且得以就此起;

 

—————拓展————————–

1.1&1.7 见  数组与字符串http://www.cnblogs.com/andy1202go/p/5759047.html

 

17.1 无缓存交换

呼吁编写一个函数,函数内未采用任何临时变量,直接交换两只数之价。

深受一定一个int数组AB,其第零个要素与率先单要素也急需交换的值,请返回交换后的数组。

测试样例:

[1,2]

返回:[2,1]

自己的笔触是直的公式退出去就哼啊:

import java.util.*;

public class Exchange {
    public int[] exchangeAB(int[] AB) {
        AB[0]=AB[0]+AB[1];
        AB[1]=-(AB[1]-AB[0]);
        AB[0]=AB[0]-AB[1];
        return AB;
    }
}

 

修及之各运算解法没看明白。。。。

a=a^b;
b=a^b;//懂了,b=(a^b)^b=a;
a=a^b;

 

妈蛋,有接触决心!!!

 

 

 

 

18.1 另类加法

不要加号的加法

核心思路:位运算;

貌似:捣腾出进位再展开相加之类的

public class Solution {
    public int getSum(int a, int b) {
        int[] array=new int[]{a,b};
        getReal(array);
        int sum=array[0]|array[1];
        return sum;
    }

    public void getReal(int[] array)
    {
        int jinWei=array[0]&array[1];
        int mask=~jinWei;
        int huo=array[0]|array[1];
        array[0]=mask&huo;
        array[1]=jinWei<<1;
        int state=array[0]&array[1];

        if (state!=0){
            getReal(array);
        }
    }
}

 进阶:高级一点之递归

import java.util.*;

public class UnusualAdd {
    public int addAB(int A, int B) {
         if (A==0) return B;
        if (B==0) return A;
        int a=A^B,b=(A&B)<<1;
        return addAB(a,b);
    }
}

 

 

18.4 有几个2

求编写一个措施,输出0到n(包括n)中数字2油然而生了几糟糕。

让一定一个刚好整数n,请返回0到n的数字被2涌出了几乎次等。

测试样例:

10

返回:1

诚如思路,每一个勤这么看下便好

import java.util.*;

public class Count2 {
    public int countNumberOf2s(int n) {
        //要全部,看起来就像是递归
        int count=0;
        if (n<2) return count;
        for(int i=2;i<=n;i++) {
            count+=num2(i);
        }
        return count;
    }

    int num2(int n){
        int count=0;
        while(n>0){
            if (n%10==2){
                count++;
            }
            n=n/10;
        }
        return count;
    }

}

 

算法复杂度太怪,时间太长。

摸规律,得下(我tm还尚未打明白)

import java.util.*;

public class Count2
{
    public int countNumberOf2s(int n)
    {
        int result = 0;
        for(int i=1;i<=n;i*=10)
        {
            result+=(n/i+7)/10*i+(n/i%10==2?n%i+1:0)  ;      
        }
        return result;


    }
}

 

各级十加倍循环一下,然后针对之十倍中起些许2进行演算。

极初步想的是为此递归,不是颇好做,而且也是各个一个这样做,时间呢太长。

 

相关文章

No Comments, Be The First!
近期评论
    分类目录
    功能
    网站地图xml地图