CodeChef-CIEL8STR : Ciel and New Menu
問題概要
0~9の並んだ列が与えられる(長さN<10^6)。leading zeroでない部分文字列のうち、8の倍数がいくつあるか(重複あり)を数える問題。
解法
1,2,3桁はそれぞれ真面目にやる。4桁以上のは、下3桁が8の倍数であればよいので、下3桁を全部試してそれ以上は非ゼロな要素の個数だけ足してやればよい。
#include <cstdio> #include <cstring> using namespace std; typedef long long int64; const int MAX_L = 1e6; char buf[MAX_L + 1]; int non_zero_accum[MAX_L + 1]; int64 solve(){ int64 ans = 0; const int N = strlen(buf); //1けた for(int i=0; i<N; i++){ if(buf[i] == '0' || buf[i] == '8'){ ans++; } } //2けた for(int i=0; i+1<N; i++)if(buf[i]!='0'){ int test = (buf[i]&15)*10 + (buf[i+1]&15); if(test%8 == 0){ ans++; } } //3けた for(int i=0; i+2<N; i++)if(buf[i]!='0'){ int test = (buf[i]&15)*100 + (buf[i+1]&15)*10 + (buf[i+2]&15); if(test%8 == 0){ ans++; } } //3けた以上 for(int i=0; i<N; i++){ non_zero_accum[i+1] = non_zero_accum[i] + (buf[i]=='0' ? 0 : 1); } for(int i=1; i+2<N; i++){ int test = (buf[i]&15)*100 + (buf[i+1]&15)*10 + (buf[i+2]&15); if(test % 8 == 0){ ans += non_zero_accum[i]; } } return ans; } int main(){ scanf("%[^\n]%*c", buf); printf("%lld\n", solve()); return 0; }