P4929小凯的数字 -题解
题目
分析
\(0 ∼ 50pts\)
只需按需枚举\(l到r\)之间的数字十进制拆位求和再取模即可
\(70pts\)
数据的\(l与r\)都在\(1e6\)的范围内\(,Q的数据达到了1e3\),在线朴素算法已经没法解决,考虑离线做法
因为只有查询,所以考虑莫队算法
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define int long long
const int p=1e6+5;
#define MAXN 1005
template<typename _T>
inline void read(_T &x)
{
x=0;char s=getchar();int f=1;
while(s<'0'||s>'9'){f=1;if(s =='-')f=-1;s=getchar();}
while('0'<=s&&s<='9'){x=(x<<1)+(x<<3)+s-'0';s=getchar();}
x*=f;
}
int tot;
struct query{
int l,r;
int id;
int place;
}ans[MAXN];
inline bool cmp(query a,query b)
{
if(a.place != b.place)
return a.place < b.place;
else
{
if(a.place&1) return a.r < b.r;
else return a.r > b.r;
}
}
int now=0;
int sp[p];
void count(int x)
{
now =x;
while(x)
{
sp[now]+=x%10;
x/=10;
}
}
int l=1,r=0;
int T,Q;
int Ans[MAXN];
inline void solve()
{
now = 0;
for(int i=1,ql,qr,ie;i<=Q;i++)
{
ql = ans[i].l;
qr = ans[i].r;
ie = ans[i].id;
while(r<qr){now+=sp[++r];now%=9;}
while(r>qr){now-=sp[r--];now%=9;}
while(l<ql){now-=sp[l++];now%=9;}
while(l>ql){now+=sp[--l];now%=9;}
Ans[ie] = (now%9+9)%9;
}
}
signed main()
{
for(int i=1;i<=1e6;i++)
count(i);//预处理
read(Q);
int T = sqrt(1e6);
for(int i=1;i<=Q;i++)
{
read(ans[i].l);
read(ans[i].r);
ans[i].id= i;
ans[i].place = (ans[i].l+1)/T;
}
sort(ans+1,ans+1+Q,cmp);
solve();
for(int i=1;i<=Q;i++)
{
cout<<Ans[i]<<'\n';
}
}
\(100pts\)
题目最后的数据已经明示我们用\(O(1)\)算法
已经想到了\(10\)进制拆位相加,\(wdnmd\)为什么想不到等差数列呢\(?\)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define int long long
template<typename _T>
inline void read(_T &x)
{
x=0;char s=getchar();int f=1;
while(s<'0'||'9'<s){f=1;if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+s-'0';s=getchar();}
x*=f;
}
signed main()
{
int T;
read(T);
while(T--)
{
int l,r;
read(l);
read(r);
int x;
x = ((l+r)%9);
x*=((r-l+1)%9);x*=5;
x%=9;
cout<<x<<'\n';
}
}