题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4669
题意:给一串数字连乘一个环,求连续的子串中组成的新的数字能被K整除的个数。
首先容易想到用DP来解,f[i][j]表示以第 i 个数字结尾的所有前缀数中,余数为 j 的个数,那么Σ(f[i][0])就是答案。
f[i][ j*10^len(num[i])+num[i] ]+=f[i][j]。
但是这个要处理环的问题,所以我们要保证每次求的f[i][j]长度不能超过n。所以我们需要在转移f[i][j]的时候,要求出以当前数字num[i]开始的长度为n的数的余数r[i],那么在统计完f[i][0],后f[i][r[i]]--。其中r[i]还是好推的,r[i]=( r[i-1]-num[i]*10^(n-len[i]) )*10^len[i] + num[i] )%m = ( r[i-1]*10^len[i] -num[i]*10^s +num[i] )%m,其中s为总长度,len[i]为当前数字num[i]的位数。。
1 //STATUS:C++_AC_203MS_1232KB 2 #include <functional> 3 #include <algorithm> 4 #include <iostream> 5 //#include <ext/rope> 6 #include <fstream> 7 #include <sstream> 8 #include <iomanip> 9 #include <numeric> 10 #include <cstring> 11 #include <cassert> 12 #include <cstdio> 13 #include <string> 14 #include <vector> 15 #include <bitset> 16 #include <queue> 17 #include <stack> 18 #include <cmath> 19 #include <ctime> 20 #include <list> 21 #include <set> 22 #include <map> 23 using namespace std; 24 //#pragma comment(linker,"/STACK:102400000,102400000") 25 //using namespace __gnu_cxx; 26 //define 27 #define pii pair<int,int> 28 #define mem(a,b) memset(a,b,sizeof(a)) 29 #define lson l,mid,rt<<1 30 #define rson mid+1,r,rt<<1|1 31 #define PI acos(-1.0) 32 //typedef 33 typedef __int64 LL; 34 typedef unsigned __int64 ULL; 35 //const 36 const int N=50010; 37 const int INF=0x3f3f3f3f; 38 //const LL MOD=1000000007,STA=8000010; 39 const LL LNF=1LL<<55; 40 const double EPS=1e-9; 41 const double OO=1e30; 42 const int dx[4]={-1,0,1,0}; 43 const int dy[4]={0,1,0,-1}; 44 const int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; 45 //Daily Use ... 46 inline int sign(double x){return (x>EPS)-(x<-EPS);} 47 template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;} 48 template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;} 49 template<class T> inline T lcm(T a,T b,T d){return a/d*b;} 50 template<class T> inline T Min(T a,T b){return a<b?a:b;} 51 template<class T> inline T Max(T a,T b){return a>b?a:b;} 52 template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);} 53 template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);} 54 template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));} 55 template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));} 56 //End 57 58 int f[2][205],len[N],num[N],ten[N<<2]; 59 int n,m; 60 61 inline int getlen(int a) 62 { 63 int ret=0; 64 while(a){ 65 ret++; 66 a/=10; 67 } 68 return ret; 69 } 70 71 int main(){ 72 // freopen("in.txt","r",stdin); 73 int i,j,p,t,r,s; 74 LL ans; 75 while(~scanf("%d%d",&n,&m)) 76 { 77 s=0; 78 for(i=1;i<=n;i++){ 79 scanf("%d",&num[i]); 80 s+=len[i]=getlen(num[i]); 81 num[i]%=m; 82 } 83 84 ten[0]=1; 85 for(i=1;i<=s;i++)ten[i]=(ten[i-1]*10)%m; 86 mem(f[0],0); 87 for(t=r=0,i=n;i>0;i--){ 88 r=(num[i]*ten[t]+r)%m; 89 t+=len[i]; 90 f[0][r]++; 91 } 92 ans=f[0][0];f[0][r]--; 93 for(i=1,p=0;i<n;i++){ 94 mem(f[p=!p],0); 95 for(j=0;j<m;j++) 96 f[p][(j*ten[len[i]]+num[i])%m]+=f[!p][j]; 97 f[p][num[i]]++; 98 ans+=(LL)f[p][0]; 99 r=(r*ten[len[i]]-num[i]*ten[s]+num[i])%m; 100 if(r<0)r+=m; 101 f[p][r]--; 102 } 103 104 printf("%I64d ",ans); 105 } 106 return 0; 107 }