1 条题解
-
0

#include<bits/stdc++.h> using namespace std; using ll=long long; const int MOD = 998244353; int dp[80][12][12][12][2][2][2][2][2][2]; // 记忆化数组 int p[80]; // p 用来存上限的每一位,从下标1开始储存,下标越大,越高位 int a1,a2,a3; // u 当前搜索的位数 // r1,2,3 目前 x1,2,3 对 a1,2,3的余数 // l1,2,3 x1,2,3是否贴着上界 int dfs(int u,int r1,int r2,int r3,bool l1,bool l2,bool l3, bool z1,bool z2,bool z3){ if(u==0){ // 并且都填过了数 // 搜索结束了,那么只要三个余数都为0,这就是一个合法的答案 return !z1 &&!z2&&!z3 && !r1&&!r2&&!r3; } // 我们记忆化所有参数 if(dp[u][r1][r2][r3][l1][l2][l3][z1][z2][z3]!=-1) return dp[u][r1][r2][r3][l1][l2][l3][z1][z2][z3]; // 三个数的上界 int up1=l1?p[u]:1,up2=l2?p[u]:1,up3=l3?p[u]:1; int ans = 0; for(ll i=0;i<=up1;i++){ for(ll j=0;j<=up2;j++){ for(ll k=0;k<=up3;k++){ if((i^j^k)!=0)continue; // 保证异或和为0 // 新的余数是原来的余数加上这一位的贡献模a int newr1 = ((ll)r1+(i<<(u-1)))%a1; int newr2 = ((ll)r2+(j<<(u-1)))%a2; int newr3 = ((ll)r3+(k<<(u-1)))%a3; // 递归新的 ans = (ans +dfs(u-1,newr1,newr2,newr3, l1&&i==p[u],l2&&j==p[u],l3&&k==p[u], z1&&i==0,z2&&j==0,z3&&k==0))%MOD; } } } return dp[u][r1][r2][r3][l1][l2][l3][z1][z2][z3]=ans; // 保存记忆化 } int main(){ ios::sync_with_stdio(0);cin.tie(0); memset(dp,-1,sizeof(dp)); ll n; cin>>n>>a1>>a2>>a3; int cnt = 0; ll x=n; while(x) p[++cnt]=x%2, x>>=1; ll ans = dfs(cnt,0,0,0,1,1,1,1,1,1); cout << ans << '\n'; return 0; }
- 1
信息
- ID
- 8856
- 时间
- 2000ms
- 内存
- 1024MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者