NOI模拟 GCD
1.NOIP模拟 排序2.NFLS 231031 比赛总结3.JOI2013Final/LOJ2763 现代豪宅4.省选模拟 序列5.省选模拟 过路费6.NOI模拟 序列7.NOI模拟 大战波特8.NOI模拟 Mizuki 与进化9.NOI模拟 刀客球10.NOI模拟 真夏は誰のモノ11.NOI模拟 树数术12.NOI模拟 序列
13.NOI模拟 GCD
14.NOI模拟 开关15.NOI模拟 排序幻觉16.NOI模拟 UTF-817.NOI模拟 捉迷藏18.退背包简介/NOI模拟 卖画19.CSP模拟 取模20.CSP模拟 矩阵操作21.AGC007F Shik and Copying String22.洛谷P10336 [UESTCPC 2024] 2-聚类算法23.NFLS 241014 比赛总结24.QOJ5173 染色25.洛谷P11183 [ROIR 2018 Day2] 大数据处理涉及知识点:数位DP,容斥原理
题意
令 表示 十进制表示下各数位乘积,则一个数对是正确的当且仅当满足以下条件:
给你 求有多少正确的有序数对。答案对 取模。
思路
由于 为“数位”的乘积,我们知道一个 的数的质因子只有可能为 ,因此乘起来质因子也只有这四个,而且发现这四个质因子个数的有效组合其实只有 级别。
记 为满足 且满足 的 的个数。这东西可以数位 DP。
那么满足 的 有序数对的个数为:
这是个容斥式, 意味着 的情况数。
设 时,我们通过上述容斥式算出了 的情况数。具体做法可以理解为用 减去了 这几种情况的并集(也就是 存在质因子对应的指数取 大于我们想要的情况)。
我们又知道 ,因此就算出来了满足 的 有序数对的个数。
最后遍历一下质因子之积 的所有组合统计答案即可。
代码
数位 DP 部分较为容易,直接看代码吧。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL P=998244353;
const int MAXDIG=20;
LL n,K,ans=0,f[MAXDIG][61][39][27][23];
bool vis[MAXDIG][61][39][27][23];
int num[MAXDIG],numlen=0;
LL dfs(int dep,bool zero,bool limit,int i,int j,int k,int l){
if(i/3+j/2+k+l>dep) return 0;//剪枝
if(dep==0) return !zero && !i && !j && !k && !l;
if(!zero && !limit && vis[dep][i][j][k][l]) return f[dep][i][j][k][l];
int dig=limit?num[dep]:9;
LL res=0;
if(zero) res=(res+dfs(dep-1,true,limit&&(dig==0),i,j,k,l))%P;
for(int p=1;p<=dig;p++){
res=(res+dfs(dep-1,false,limit&&(dig==p),max(i-(!(p%2))-(!(p%4))-(!(p%8)),0),max(j-(!(p%3))-(!(p%9)),0),max(k-(!(p%5)),0),max(l-(!(p%7)),0)))%P;
}
if(!zero && !limit){
vis[dep][i][j][k][l]=true;
f[dep][i][j][k][l]=res;
}
return res;
}
LL calc(int i,int j,int k,int l){
LL res=0;
for(int p2=0;p2<=1;p2++)
for(int p3=0;p3<=1;p3++)
for(int p5=0;p5<=1;p5++)
for(int p7=0;p7<=1;p7++){
LL tmp=dfs(numlen,true,true,i+p2,j+p3,k+p5,l+p7);
res=(res+1LL*((p2+p3+p5+p7)%2?P-1:1)*tmp%P*tmp%P)%P;
}
return res;
}
int main(){
// freopen("b.in","r",stdin);
// freopen("b.out","w",stdout);
cin>>n>>K;
while(n){
num[++numlen]=n%10;
n/=10;
}
LL tmp2,tmp3,tmp5,tmp7;
tmp2=1;
for(int i=0;tmp2<=K;i++,tmp2*=2){
tmp3=1;
for(int j=0;tmp2*tmp3<=K;j++,tmp3*=3){
tmp5=1;
for(int k=0;tmp2*tmp3*tmp5<=K;k++,tmp5*=5){
tmp7=1;
for(int l=0;tmp2*tmp3*tmp5*tmp7<=K;l++,tmp7*=7){
ans=(ans+calc(i,j,k,l))%P;
}
}
}
}
cout<<ans<<endl;
return 0;
}
本文作者:MessageBoxA
本文链接:https://www.cnblogs.com/SkyNet-PKN/p/18211336
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步