题目描述
问是否可以将一个仅由0~9组成的字符串划分成两个或两个以上部分,使得每一部分的数字总和相等。
输入
输入文件名为 (divide.in)
多组数据,第一行一个数(n),表示数据组数
接下来(n)行,每行包含一个字符串
输出
输出文件名为(divide.out)
输出n行,每行为 (’YES’) 或者 (’NO’) ,表示是否存在题目要求的划分方案。
样例输入
3
1248
2680
54174760
样例输出
NO
YES
YES
提示
【数据说明】
对于50%的数据,$ 2 le Length le 100 $
对于100%的数据,$ 1 le n le 5 , 2 le Length le 10^5 $
啊,这个题,我一直以为挺难的,是个DP,结果后来发现枚举就行.....当时心里那个mmp
枚举就简单了啊
我是枚举分成多少段,然后在原数列中去 $ check $ 是否可行,至于每一段的和,直接用总和作除法就行了
当然,如果说根本无法分成当前枚举到的段数,那么直接 $ continue $
否则就一直凑就行了,每一段的和我是维护前缀和然后 (Theta(1)) 求的,这个题总体比较简单,毕竟是 CF Div2 的 C题改过来的,也不是很难
至于代码.....如下吧:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#define LL long long
const int N = 1e5 + 5 ;
LL T , sum[N] ;
char s[N] ;
bool f ;
inline LL read(){
LL x = 0 , f = 1 ;char ch = getchar ();
while ( ch < '0' || ch > '9' ){if ( ch == '-' ) f = - 1 ;ch = getchar ();}
while ( ch >= '0' && ch <= '9' ){x = ( x << 3 ) + ( x << 1 ) + ( ch ^ 48 ) ;ch = getchar () ; }
return f * x ;
}
int main(){
T = read (); sum[0] = 0 ;
while ( T -- ){
scanf ("%s" , s + 1 ) ; f = false ;
register int L = strlen ( s + 1 ) ;
for ( int i = 1 ; i <= L ; ++ i)
sum [i] = sum [ i - 1 ] + s[i] - '0' ;
if ( sum[L] == 0 ) { puts("YES") ; continue ;}
for ( int i = 2 ; i <= sum[L] ; ++ i){ // 枚举分成多少段
if ( sum[L] % i ) continue ; // 连整除都做不到还要你作甚
register int tmp = sum[L] / i , k = 0 ; // tmp是每段的和 , k是当前是第几段
if ( tmp == sum[L] ) continue ;
for (int j = 1 ; j <= L ; ++ j){
if ( sum[j] - k * tmp == tmp ) ++ k ; // 如果当前枚举到的子段和恰好与枚举的和相等,继续推进
else if ( sum[j] - k * tmp > tmp ) break ;// 否则,如果比当前枚举的和大,那么直接跳过,不鸟他
}
if ( k == i ) { f = true ; break ;}
}
if ( f ) puts ("YES");
else puts ("NO");
}
return 0;
}