您的位置:首页 > 其它

zoj 3845 Fixed Point(数位dp)

2015-01-11 21:18 363 查看
题目链接

Fixed Point

Time Limit: 2 Seconds
Memory Limit: 65536 KB

In mathematics, a fixed point (sometimes shortened to fixpoint, also known as an invariant point) of a function is an element of the function's domain that is mapped to itself by the function. A set of fixed points is sometimes called a fixed set. That is
to say, c is a fixed point of the function f(x) if and only if
f(c) = c. This means f(f(...f(c)...)) =
fn(c) = c, an important terminating consideration when recursively computing
f. For example, if f is defined on the real numbers by
f(x) = x2 - 3x + 4, then 2 is a fixed point of
f, because f(2) = 2.

Bob has three funtions define on nonegative integers, A(x) =
c ∧ x, E(x) = c ⊕ x, and
O(x) = c ∨ x, where ∧ means bitwise AND operation, ⊕ means bitwise XOR operation, ∨ means bitwise OR operation and
c is an integer constant.

Bob wants to know the number of fixed points for each function which satisfy the following conditions:

x is no less than L and x is also no greater than
R.
Let c0 be the number of 0-bit in x's binary representation and
c1 be the number of 1-bit in x's binary representation. Then we have |c0 -
c1| ≤ k.

You are given three integers L, R and k, please tell Bob the answer.

Note: x is a 32-bit integer, that is x's binary representation only has 32 bits.

Input

The first line of input contain an integer T (T ≤ 10000), which is the number of cases.

Then next T line, each line contain four integers L,
R, c and k (0 ≤ L ≤ R < 232, 0 ≤
c < 232, 0 ≤ k ≤ 32), separated by spaces.

Output

For each test case, print a line containing the test case number (beginning with 1) followed by three integers, indicating the number of fixed points for function
A(x), E(x) and O(x), separated by one space.

Sample Input

3
1 10 1 32
1 100 43 32
1 200 43 20

Sample Output

Case 1: 1 0 5
Case 2: 15 0 4
Case 3: 0 0 7


题意:A(x)=c&x, B(x)=c^x,C(x)=c|x。分别求出在[L,R]的范围内,满足A(x)=x,B(x)=x,C(x)=x,且32位二进制表示中1的个数和0的个数的差的绝对值小于等于k的数的个数。

题解:由于数的范围较大,所以要用数位统计的方法。先将数转换到二进制。用dp[i][j] 表示从32位到第i位的数,二进制0,1的绝对值之差为j,由当前状态变到目标状态的数的个数。转移的时候分别满足A(x)=x,B(x)=x.C(x)=x的条件。

代码如下:

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<string>
#include<stack>
#include<math.h>
#include<vector>
#include<set>
#include<map>
#define nn 110000
#define inff 0x7fffffff
#define eps 1e-8
#define mod 1000000007
typedef long long LL;
const LL inf64=LL(inff)*inff;
using namespace std;
LL l,r,c,k;
LL wc[40];
LL wei[40];
LL dp[40][70];
LL dfs(int id,int s,int ty,bool man)
{
if(id==-1)
{
if(abs(s-35)<=k)
return 1;
return 0;
}
if(!man&&dp[id][s]!=-1)
return dp[id][s];
int end=man?wei[id]:1;
LL re=0;
for(int i=0;i<=end;i++)
{
if(ty==1)
{
if((wc[id]&i)==i)
{
if(i==0)
re+=dfs(id-1,s-1,ty,man&&i==end);
else
re+=dfs(id-1,s+1,ty,man&&i==end);
}
}
if(ty==2)
{
if((wc[id]^i)==i)
re+=dfs(id-1,i==0?(s-1):(s+1),ty,man&&i==end);
}
if(ty==3)
{
if((wc[id]|i)==i)
re+=dfs(id-1,i==0?(s-1):(s+1),ty,man&&i==end);
}
}
if(!man)
dp[id][s]=re;
return re;
}
LL solve(LL x,int ty)
{
int ix=0;
memset(wei,0,sizeof(wei));
while(x)
{
wei[ix++]=x%2;
x/=2;
}
return dfs(31,35,ty,true);
}
int main()
{
int t,cas=1;
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld%lld%lld",&l,&r,&c,&k);
LL ans1,ans2,ans3;
int ix=0;
LL ic=c;
memset(wc,0,sizeof(wc));
while(c)
{
wc[ix++]=c%2;
c/=2;
}
if(l==0)
{
memset(dp,-1,sizeof(dp));
ans1=solve(r,1);
memset(dp,-1,sizeof(dp));
ans2=solve(r,2);
memset(dp,-1,sizeof(dp));
ans3=solve(r,3);
}
else
{
memset(dp,-1,sizeof(dp));
ans1=solve(r,1)-solve(l-1,1);
memset(dp,-1,sizeof(dp));
ans2=solve(r,2)-solve(l-1,2);
memset(dp,-1,sizeof(dp));
ans3=solve(r,3)-solve(l-1,3);
}
printf("Case %d: ",cas++);
printf("%lld %lld %lld\n",ans1,ans2,ans3);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: