P4067 [SDOI2016] 储能表 题解
因为不能直接减去
这样就可以进行数位 dp 了。令
转移是简单的,即
为了实现方便,返回值是一个 pair 即可只用一次记搜。
代码:
typedef long long ll;
typedef pair<int,int> pii;
ll n,m,k;int p;
ll pw[65];
pii f[64][2][2][2];int vis[64][2][2][2];
pii dfs(int bit,int un,int um,int lk){
if(bit==-1)return pii(1,0);
if(vis[bit][un][um][lk])return f[bit][un][um][lk];
vis[bit][un][um][lk]=1;
pii &now=f[bit][un][um][lk];
now=pii(0,0);
int bn=n>>bit&1,bm=m>>bit&1,bk=k>>bit&1;
for(int i=0;i<=(un?bn:1);i++)for(int j=0;j<=(um?bm:1);j++){
if(lk&&(i^j)<bk)continue;
pii res=dfs(bit-1,un&(i==bn),um&(j==bm),lk&((i^j)==bk));
now.first=(now.first+res.first)%p,now.second=(now.second+res.first*(i^j)*1ll*pw[bit]+res.second)%p;
}
return now;
}
void solve(){memset(vis,0,sizeof(vis));
scanf("%lld%lld%lld%d",&n,&m,&k,&p);n--,m--;
pw[0]=1;for(int i=1;i<=60;i++)pw[i]=pw[i-1]*2%p;
pii res=dfs(60,1,1,1);
cout<<(res.second-res.first*1ll*(k%p)%p+p)%p<<"\n";
}
int main(){
int T;cin>>T;
while(T--)solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?