2015 ACM/ICPC 北京赛区 现场赛 K — A Math Problem【规律+数位dp】

http://media.hihocoder.com/contests/icpcbeijing2015/problems.pdf

题意:

给你两个数n(n<=1e18),mod(mod=3,5,7,257,65537)

定义f(x):

f(1)=1;

已知:3*f(n)*f(2*n+1)=f(2*n)*(1+3*f(n));

           f(2*n)<6*f(n);

          将f(1)~f(n)%mod。

结果:求模之后结果为0~mod-1的数字的数量的异或。

分析:

这个题只要找出来规律就是一个简单的数位dp,规律就是n写成二进制的方法,用三进制来计算例如5=101,结果f[5]=101(三进制)=10;

代码:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=62;
ll dp[maxn][5][65538];
int mp[65538],a[maxn],mm;
int mo;
ll n;
int yu[maxn];
ll dfs(int pos,int v,bool limit)
{
    if(pos==-1) return (v==0);
    if(!limit&&dp[pos][mm][v]!=-1) return dp[pos][mm][v];
    ll ans=0;
    int end=limit?a[pos]:1;
    int vv=v;
    for(int i=0;i<=end;i++)
    {
        if(i&1) {v-=yu[pos];v=(v+mo)%mo;}
        ans+=dfs(pos-1,v,limit&&i==end);
    }
    if(!limit) dp[pos][mm][vv]=ans;
    return ans;
}
ll solve(ll x)
{
   // cout<<x<<endl;
    mm=mp[mo];
    yu[0]=1;
    for(int i=1;i<maxn;i++)yu[i]=(yu[i-1]*3)%mo;
    int pos=0;
    while(x)
    {
        a[pos++]=x&1;
        x>>=1;
    }
    ll ans=0;
    for(int i=0;i<mo;i++)
    {
        ans^=(dfs(pos-1,i,1)-(i==0));
        //cout<<(dfs(pos-1,i,1)-(i==0))<<endl;
    }
    return ans;
}
int main()
{
    mp[3]=0;mp[5]=1;mp[17]=2;
    mp[257]=3;mp[65537]=4;
    memset(dp,-1,sizeof(dp));
    int T,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%d",&n,&mo);
        printf("%lld\n",solve(n));
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值