[数位DP]JZOJ 3363 Number
分析
搞一波类似于容斥的东西,然后把不合法全部枚举出来,在转移过程中如果与不合法匹配则直接归0
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int w[10][2]={{0,0},{3,3},{4,4},{5,5},{7,3},{7,4},{8,3},{8,4},{11,3},{11,4}}; int pow[11]={1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000}; int ways[100001][101]; long long f[12][100001],ans; int a[101][2]; int n; int main() { scanf("%d",&n); for (int i=1;i<=n;i++) { char s[6]; scanf("%s",s+1); a[i][0]=strlen(s+1); for (int j=a[i][0];j;j--) a[i][1]=a[i][1]*10+s[j]-'0'; } for (int i=1;i<=n;i++) for (int j=0;j<=99999;j++) for (int k=1;k<=6-a[i][0];k++) if (j%pow[a[i][0]+k-1]/pow[k-1]==a[i][1]) { ways[j][++ways[j][0]]=a[i][0]+k-1; break; } f[0][0]=1; for (int i=1;i<=11;i++) { for (int j=0;j<=99999;j++) for (int k=0;k<=9;k++) f[i][j%pow[4]*10+k]+=f[i-1][j]; for (int k=1;k<=9;k++) if (w[k][0]==i) for (int j=0;j<=99999;j++) if (f[i][j]) for (int l=1;l<=ways[j][0];l++) if (ways[j][l]<=w[k][1]) { f[i][j]=0; break; } } for (int i=0;i<=99999;i++) if (i%10==1) ans+=f[11][i]; printf("%lld",ans); }
在日渐沉没的世界里,我发现了你。