AOJ 1310 ICPC Asia resional 2010 Problem F: Find the Multiples
制約条件
n≦10^5
Q≦10^8
方針
部分文字列をa[i]a[i+1]...a[j]とする。
するとこの文字列をXとおけばXは、
a[0]+10*a[1]+...+10^k*a[k] = S[k]として、
S[i] - S[j] = 10^j * Xを満たす。
ここでXとQが互いに素であるならば、X mod Q⇔S[i] - S[j] = 0である。
ここから次のような解法が導ける。
Qが2または5でない場合は、桁を下の桁から順に見ていく。
桁ごとに、その時点までに出てきた同じ余りの数を答えに足せばいい。
Qが2または5の場合、桁を上のほうから見ていき、
Qの倍数の桁があったら、いままでに出てきた0でない数字の数だけ答えを増やす。
ソースコード
int n,s,w,q,a[100000]; void solve25(){ ll ans=0; int nonzero=0; rep(i,n){ if(a[i])nonzero++; if(a[i]%q==0)ans+=nonzero; } cout<<ans<<endl; } void solve(){ ll ans=0; map<int,int> cnt; cnt[0]=1; ll mod=0,ten=1; for(int i=n-1;i>=0;i--){ (mod+=ten*a[i])%=q; (ten*=10)%=q; if(a[i])ans+=cnt[mod]; cnt[mod]++; } cout<<ans<<endl; } int main() { while(scanf("%d%d%d%d",&n,&s,&w,&q),n){ rep(i,n){ a[i]=s/7%10; if(s%2==0)s/=2; else s=(s/2)^w; } //rep(i,n)cerr<<a[i]<<" "; cerr<<endl; if(q==5||q==2)solve25(); else solve(); } return 0; }