zoukankan      html  css  js  c++  java
  • [AtCoder2272] Xor Sum

    题目

    原题地址

    解说

    自己选的分享题自己看了半天不会
    大致题意就是给出正整数(N),求出整数对(u)(v(0≤u,v≤N))的数目,使得存在两个非负整数(a)(b)满足(a xor b = u)(a + b= v)。这里,(xor)表示按位异或。 要求对答案取模(10^9 + 7)
    先用下面的代码暴力了一遍:

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
    	int n;
    	cin>>n;
    	for(int i=0;i<=n;i++){
    		int ans=0;
    		/*cout<<i<<':'<<endl;*/
    		for(int v=0;v<=i;v++){
    			for(int u=0;u<=v;u++){
    				for(int a=0;a<=v/2;a++){
    					if(((v-a)^a)==u){
    						ans++;
    						/*cout<<v<<' '<<u<<endl;*/
    						break;
    					}
    				}
    			}
    		}
    		cout<<ans<<endl;
    	}
    }
    

    之后就像研究数列一样研究了半天,发现规律(a_0=1,a_1=2),之后(a_n=a_{n/2}+a_{(n-1)/2}+a_{(n-2)/2})
    那就按照这个思路写吧。这就是一个简单的递推了还不简单?由于(10^{18})太大数组开不下,只能用(map)。之后就递归还是(for)循环就随意了。
    大功告成!但是好像只观察出了规律没证明……
    看了半天还是不会证明……白嫖一个吧……

    其实在本质上看的二进制操作也比较好理解,要得到小于等于(n)的数,第一种操作是(n/2)即先将(n>>1),然后(n<<1),这样最后得到的数肯定不会超过(n),第二种操作是(((n-1)/2)*2+((n-1)/2)),第三种操作是(((n-2)/2)*2+1 + ((n-2)/2)*2+1),三种操作目的很明显,完成递推且数对数对(a,b)进行的操作不能使(a+b)出现大于(n)的情况。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=1e9+7;
    map<ll,ll> a; 
    ll dfs(ll x){
    	if(a[x]) return a[x];
    	a[x]=(dfs(x/2)+dfs((x-1)/2)+dfs((x-2)/2))%mod;
    	return a[x];
    }
    int main(){
    	a[0]=1;
    	a[1]=2;
    	ll n;
    	scanf("%lld",&n);
    	ll ans=dfs(n);
    	printf("%lld",ans);
    	return 0;
    } 
    

    幸甚至哉,歌以咏志。

  • 相关阅读:
    MongoDB的Spring-data-mongodb集成(Win10 x64) 第一章
    Linux 环境部署记录(三)
    onsubmit不起作用的原因
    sql server 将时间中的时分秒改为00:00:00
    js文件被浏览器缓存
    Action<>和Func<> 区别
    sql2008 express 实现自动备份
    Centos 7 无法上网的解决办法
    js 中的[] {}是什么意思
    js中var a={}什么意思
  • 原文地址:https://www.cnblogs.com/DarthVictor/p/12860407.html
Copyright © 2011-2022 走看看