CF107D Crime Management
我们发现乘积小于等于 123 ,设 muli=c∏j=1mj[tj=i] ,就是相当于这一种限制的积,然后我们发现在每一种的个数对 muli 取膜的情况下,状态数最多只有 123 种,就可以考虑把状态压缩为一维。
发现根本不需要搜出所有状态再给编号,考虑一个二维矩阵中的坐标我们是如何把它转成一个数的,这里就相当于多维的坐标,编号就可以变为:
((r1×mul2+r2)×mul3+r3)... (这里 ri 为对 muli 取膜以后的数)
所以可以进行 DP
然而 n≤1018 ,发现对于从选 i 个到选 i+1 个,怎么转移与 i 无关,可以在一开始处理出来,所以每一次转移其实本质上都一样,就可以直接套矩阵快速幂了
注意最后答案不是 f0 ,因为有些种类虽然膜 muli 不为 0 ,但是可能膜某一个 mj 为 0 ,需要枚举每种状态是否可行,然后可行就加上即可
code :
#include<cstdio> #include<cctype> #include<vector> using namespace std; #define maxn 33 #define maxs 222 #define maxc 1111 #define mod 12345 inline long long read(){ long long r=0,f=0; char c; while(!isdigit(c=getchar()))f|=(c=='-'); while(isdigit(c))r=(r<<1)+(r<<3)+(c^48),c=getchar(); return f?-r:r; } inline char get_c(){ char c; while(!isalpha(c=getchar())); return c; } int N=1; long long n; int cnt,mul[maxn]; long long ans,f[maxs],a[maxs][maxs],c[maxs][maxs]; vector<int> m[maxn]; inline void mulself(){ for(int i=0;i<N;i++) for(int j=0;j<N;j++) for(int k=0;k<N;k++) (c[i][j]+=a[i][k]*a[k][j]%mod)%=mod; for(int i=0;i<N;i++) for(int j=0;j<N;j++){ a[i][j]=c[i][j]; c[i][j]=0; } } inline void multi(){ for(int i=0;i<N;i++) for(int j=0;j<N;j++) (c[0][i]+=f[j]*a[i][j]%mod)%=mod; for(int i=0;i<N;i++){ f[i]=c[0][i]; c[0][i]=0; } } int main(){ n=read(),cnt=read(); for(int i=1;i<=cnt;i++){ int t=get_c()-'A'+1; int val=read(); m[t].push_back(val); if(!mul[t])mul[t]=1; mul[t]*=val; }//没有限制的种类是不能选的,所以mul开始要全置0 for(int i=1;i<=26;i++) if(mul[i])N*=mul[i]; N++; for(int i=0;i<N;i++){//枚举对于每种状态 int num=i;//选一种以后能转移到哪一个 long long mult=1; for(int j=26;j>=1;j--){ if(!mul[j])continue; int tot=num%mul[j]; int s=i-tot*mult; tot++; tot%=mul[j]; s+=tot*mult; num/=mul[j]; mult*=mul[j]; a[s][i]++;//存在该转移 } } f[0]=1; for(;n;n>>=1){ if(n&1)multi(); mulself(); } for(int i=0;i<N;i++){//找合法状态 int num=i; bool ok=1; for(int j=26;j>=1;j--){ if(!mul[j])continue; int tot=num%mul[j]; bool b=0; for(int k=0;k<(int)m[j].size();k++) b|=((tot%m[j][k])==0);//只要满足一种即可 ok&=b; num/=mul[j]; } if(ok)(ans+=f[i])%=mod;//合法就加上,记得取膜 } printf("%lld\n",ans); return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步