选数 - 题目 - Daimayuan Online Judge
题意:
思路:
给序列做个前缀和,同时模上N
如果两个位置的前缀和模N的结果相同,那么这两个位置之间的那个数模N就是0
因为模N最多只有N种情况,前缀和有N+1种情况,因此一定存在两个位置模N的结果相同
Code:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int mxn=1e5+10;
map<int,int> mp;
int N;
int a[mxn],pre[mxn];
void solve(){
cin>>N;
for(int i=1;i<=N;i++){
cin>>a[i];
pre[i]=(pre[i-1]+a[i])%N;
}
mp[0]=0;
for(int i=1;i<=N;i++){
pre[i]%=N;
if(mp.count(pre[i])){
cout<<i-mp[pre[i]]<<'\n';
for(int j=mp[pre[i]]+1;j<=i;j++) cout<<j<<" \n"[j==i];
return;
}
mp[pre[i]]=i;
}
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int __=1;//cin>>__;
while(__--)solve();return 0;
}
D - Multiple of 2019 (atcoder.jp)
题意:
思路:
同样的道理,可以给后缀和模2019,如果两个位置模2019的结果相同,那么中间那个数就一定是2019的倍数,所以可以直接map计数
Code:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int mxn=1e5+10;
const int mxe=1e5+10;
const int mod=1e9+7;
map<int,int> mp;
string s;
void solve(){
cin>>s;
int n=s.size();
s=" "+s;
mp[0]++;
int d=1,now=0,ans=0;
for(int i=n;i>=1;i--){
now=(now+d*(s[i]-'0')%2019)%2019;
ans+=mp[now];
mp[now]++;
d=(d*10)%2019;
}
cout<<ans<<'\n';
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int __=1;//cin>>__;
while(__--)solve();return 0;
}