D

题目大意:一段数字组成的字符串,然后从对数(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); 
}
原文地址:https://www.cnblogs.com/Accepting/p/12785429.html