hdu 4588 Count The Carries
2013-08-20 12:05
302 查看
思路:容易发现二进制表示的数的最低位规律是01010101……;接着是001100110011……;接着是:0000111100001111……
这样我们发现每一位的循环节是2^(i+1),前2^i是0,后面的是1.这样就可以算出每一位1出现的次数。
代码如下:
View Code
这样我们发现每一位的循环节是2^(i+1),前2^i是0,后面的是1.这样就可以算出每一位1出现的次数。
代码如下:
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #define ll __int64 using namespace std; ll a[35]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384, 32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608, 16777216,33554432,67108864,134217728,268435456,536870912,1073741824, 2147483648,4294967296,8589934592,17179869184}; ll sa[35],sb[35],s[100]; int get(int n) { int bit=0; while(n){ bit++; n>>=1; } return bit; } void solve(int n,ll *aa) { ll i,j,nn=n+1; if(n<=0) return; int len=get(n); for(int k=0;k<len;k++){ aa[k]+=nn/a[k+1]*a[k]; j=nn%a[k+1]; if(j>=a[k]) j-=a[k]; else j=0; aa[k]+=j; } } int main() { int n,m,len1,len2; ll c; while(scanf("%d%d",&n,&m)!=EOF){ memset(sa,0,sizeof(sa)); memset(sb,0,sizeof(sb)); memset(s,0,sizeof(s)); solve(m,sa); solve(n-1,sb); for(int i=0;i<35;i++) s[i]=sa[i]-sb[i]; ll ans=0; for(int i=0;i<100;i++){ c=(s[i]>>1); ans+=c; s[i+1]+=c; } printf("%I64d\n",ans); } return 0; }
View Code
相关文章推荐
- HDU 4588 Count The Carries(数学 二进制 找规律啊)
- HDU 4588 Count The Carries 数位DP || 打表找规律
- HDU 4588 Count The Carries 数位DP || 打表找规律
- HDU 4588 Count The Carries(位运算)
- 【瞎搞】 HDU 4588 Count The Carries
- HDU-4588 Count The Carries (模拟)
- HDU 4588 Count The Carries
- hdu 4588 Count The Carries
- HDU 4588 Count The Carries(数学统计)
- HDU 4588 Count The Carries(数学)
- HDU 4588 Count The Carries (数学,计数)
- 数学题-hdu-4588-Count The Carries
- hdu 4588 Count The Carries 数学
- HDU 4588 Count The Carries(找规律,模拟)
- HDU 4588 Count The Carries 数学
- Hdu 4588 Count The Carries(数位统计)
- HDU 4588 Count The Carries (2013年南京邀请赛)
- HDU 4588 Count The Carries
- HDU 4588 Count The Carries
- hdu 4588 Count The Carries