SPOJ IGAME(Interesting Game-博弈+数位dp)

IGAME - Interesting Game
no tags
Alice and Bob play an interesting game and the game is played on a number.

So a player, on his chance, can choose any non zero digit of the number and decrease the digit by any non zero amount such that the resulting digit remains non-negative. The player who gets all the digits of the number 0 wins. Both play optimally and Alice starts first. Now tell how many numbers are there between A and B on which if the game is played Alice wins and also find how many numbers are there where Bob wins. On every number between A and B, Alice plays first on that number .

Input Format
The Input line consists of T test cases. On each line there are two numbers A and B.

Output Format
The Output line consists of T lines each having two numbers.

Constraints:
1 ≤ T ≤ 10000
1 ≤ A ≤ B ≤ 1018

Sample Input
2
1 10
101 110

Sample Output
10 0
8 2

Explanation
In the first case the first player Alice will always win because she can reduce any digit to 0.
In the second case the second player Bob will win on 2 numbers 101 and 110. Rest Alice will win.

显然Alice赢当且仅当xor和!=0
直接数位dp

#include<bits/stdc++.h> 
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,0x3f,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define MEMx(a,b) memset(a,b,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
#define ALL(x) (x).begin(),(x).end()
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
ll f[22][22];
int c[22];
ll calc(ll n) {
    int len=0;
    if (!n) return 1;
    while(n) c[++len]=n%10,n/=10;
    For(i,len/2) swap(c[i],c[len-i+1]);
    ll v=0,ans=0;
    For(i,len) {
        MEM(f)
        Rep(j,c[i]) f[i][v^j]++;
        Fork(j,i,len-1) {
            Rep(k,20)
                if (f[j][k]) 
                    Rep(l,10) f[j+1][k^l]+=f[j][k];
        }
        v^=c[i];
        ans+=f[len][0];
    }return ans+(v==0);
}
int main()
{
//  freopen("spojIGAME.in","r",stdin);
//  freopen(".out","w",stdout);
    int T=read();
    while(T--) {
        ll a,b;
        cin>>a>>b;
        ll ans=calc(b)-calc(a-1);
        ll ans2=b-a+1;
        cout<<ans2-ans<<' '<<ans<<endl;
    }


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值