HDU 4669 Mutiples on a circle (DP , 统计)
来源:互联网 发布:海典软件 垃圾 编辑:程序博客网 时间:2024/05/06 18:07
转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
题意:给出一个环,每个点是一个数字,取一个子串,使得拼接起来的数字是K的倍数。
由于K不大,暂且不考虑环的话,那么dp[i][j]表示以i结尾的,模K为j的有多少个子串。
那么sigma (dp[i][0])便是不考虑环的答案。
考虑环的话,不知道别人怎么写的,我感觉我的写法不是很复杂。
环和情况1 和n肯定是必选的,那么便是一个前缀为后缀,一个后缀为前缀拼接而成。
所以枚举某个前缀,求出前缀模K,那么枚举后缀模K的值,通过之前已经预处理过的dp值,便可以求出有多少个后缀满足为K的倍数。
但是这样可能后缀和前缀重叠了,所以我们枚举前缀的同时,依次记录后缀不同模值的个数。
随着前缀的增长,这些后缀都是和前缀重叠的。
#include <iostream>#include <cstdio>#include <cstring>#include <map>#include <vector>#include <string>#include <queue>#include <cmath>#include <algorithm>#define lson step << 1#define rson step << 1 | 1#pragma comment(linker,"/STACK:102400000,102400000")using namespace std;typedef long long LL;const int N = 50005;const int M = 205;int n , k , a[N] ,l[N];int dp[2][M] , prefix[N] , fac[N << 2] , suffix[N];int cnt[M];int cal (int x) { int cnt = 0; while (x) x /= 10 , cnt ++; return cnt;}int main () { #ifndef ONLINE_JUDGE freopen ("input.txt" , "r" , stdin); // freopen ("output.txt" , "w" , stdout); #endif while (scanf ("%d %d" , &n , &k) != EOF) { fac[0] = 1; for (int i = 1 ; i <= (n << 2) ; i ++) fac[i] = fac[i - 1] * 10 % k; for (int i = 1 ; i <= n ; i ++) { scanf ("%d" , &a[i]); l[i] = cal (a[i]); } for (int i = 0 ; i < 2 ; i ++) { for (int j = 0 ; j < k ; j ++) dp[i][j] = 0; } dp[1][a[1] % k] = 1; LL ans = dp[1][0]; for (int i = 2 ; i <= n ; i ++) { for (int j = 0 ; j < k ; j ++) dp[i & 1][j] = 0; dp[i & 1][a[i] % k] ++; for (int j = 0 ; j < k ; j ++) { dp[i & 1][(j * fac[l[i]] + a[i]) %k] += dp[(i - 1) & 1][j]; } ans += dp[i & 1][0]; } prefix[0] = 0;suffix[n + 1] = 0; for (int i = 1 ; i <= n ; i ++) { prefix[i] = (prefix[i - 1] * fac[l[i]] + a[i]) % k; } int len = 0; for (int i = n ; i >= 1 ; i --) { suffix[i] = (a[i] * fac[len] + suffix[i + 1]) % k; len += l[i]; } len = 0; for (int i = 0 ; i < k ; i ++) cnt[i] = 0; for (int i = 1 ; i <= n ; i ++) { cnt[suffix[i]] ++; len += l[i]; int p = prefix[i]; for (int j = 0 ; j < k ; j ++) { if ((j * fac[len] + p) % k) continue; ans += dp[n & 1][j] - cnt[j]; } } printf ("%I64d\n" , ans); } return 0; }
- HDU 4669 Mutiples on a circle (DP , 统计)
- hdu 4669 Mutiples on a circle(按位DP)
- hdu 4669 Mutiples on a circle
- HDU - 4669 Mutiples on a circle
- HDU 4669 Mutiples on a circle (环形数列DP)byPlato
- 2013 多校第七场 hdu 4669 Mutiples on a circle(DP,环)
- hdu 4669 Mutiples on a circle(高效)
- hdu 4669 Mutiples on a circle 多校第七场
- HDU 4669 Mutiples on a circle 解题报告
- hdu 4669——Mutiples on a circle
- HDU 4669 Mutiples on a circle (2013多校联合7 1004)
- hdoj 4669 Mutiples on a circle
- HDOJ 4669 Mutiples on a circle
- [HDU4669]Mutiples on a circle
- [agc013c]Ants on a Circle
- hdu 1700 Points on circle(三角函数应用)
- codeforces Simba on the Circle (dp)
- CodeForces 652F. Ants on a Circle
- MIPI DSI 协议介绍
- 汇率相关的一些东东
- hdu 3549 最大流入门
- 详解Java解析XML的四种方法
- Spring 1 IoC 3 DI
- HDU 4669 Mutiples on a circle (DP , 统计)
- 设计包含min函数的栈
- 八皇后问题
- poj 3693 (后缀数组)
- 最大公约数与最小公倍数
- DXF文件解析显示(读取,合并,保存)
- Spring 1 IoC 4 注解
- javafx之登陆界面的跳转
- 格式(formatting)