题目大意:一段数字组成的字符串,然后从对数(i,j)要求从i到j的数字组成的整数是2019的倍数.然后求(i,j)的对数.
题解:再一次被自己菜到。我一开始想的是从前往后走,然后乘10去余,当遇到相同的余数时,就可以确定2019的倍数了。
但是这样行不通, 因为中间数字可能会出现交叉现象,比如说样例1: 1817181712114 ,181718171就出现了交叉的现象。不妨从后往前试试看,就是我们每次都是添加最高位。
181718171 当从后往前走走到8171时,前边再加个1就能成为2019的倍数,而前边有两个1,这样就能处理交叉了。
code:
#include<bits/stdc++.h> using namespace std; typedef long long ll; int main(){ string s; cin>>s; int len=s.size(); ll ans=0,p=1,now=0,cnt[2020]={0}; cnt[0]=1; for(int i=len;i--;){ now=(now+ll(s[i]-'0')*p)%2019; ans+=cnt[now]++; p=p*10%2019; } cout<<ans<<endl; return 0; }
还有一个和这个问题十分类似的问题:
Large Division LightOJ - 1214
题面是:给定两个整数a和b,你应该检查a是否可以被b整除。我们知道,当且仅当存在整数c使得a = b * c时,整数a才能被整数b整除。
这个问题我们就可以从前往后了因为他判断的是整体,从后往前也可以的。
code:
#include<bits/stdc++.h> using namespace std; typedef long long ll; void solve(ll time){ string s; cin>>s; ll n=s.size(); ll c; cin>>c; ll i; if(s[0]=='-') i=1; else i=0; ll res=0; for(;i<n;i++){ res=res+(s[i]-'0'); res=res%c; res*=10; } printf("Case %d: ",time); cout<<(res==0? "divisible":"not divisible")<<endl; } int main(){ ll t;cin>>t; for(ll i=1;i<=t;i++) solve(i); }