题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4351
题意:
任何数的数字根是一个个位数,如45635,则它的数字根为4+5+6+3+5=23 ->2+3=5;5是它的数字根;
现在给你一串数字,再任意给出这串数的一个子串(l,r);要你求l到r中的任意连续子串的和的数字根,输出
前五个最大的不相等的数字根,若所求数不足五个,用-1补;
分析:
首先要明白每个数字的根其实就是该数字模9的结果,当然9的根还为9.
源代码:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
const int N=100005;
#define mid (tre[o].l+tre[o].r)/2
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
struct Node
{
int l,r;
int ls,rs,ms,all;/*ls表示包含区间左端点的情况,rs表示包含区间右端点的情况,ms表示此区间内所有数的和的根,all表示该区间所有情况*/
} tre[N<<2];
int mul[1024][1024];
int root(int x)
{
if(x==0)
return 0;
return x%9?(x%9):9;
}
void init()
{
for(int i=0; i<(1<<10); i++)
{
for(int j=0; j<(1<<10); j++)
{
mul[i][j]=0;
for(int p=0; p<10; p++)
if(i&(1<<p))
{
for(int q=0; q<10; q++)
if(j&(1<<q))
mul[i][j]|=(1<<root(p+q));
}
mul[j][i]=mul[i][j];
}
}
}
void pushup(int o)
{
tre[o].ls=tre[o<<1].ls|mul[tre[o<<1].ms][tre[o<<1|1].ls];
tre[o].rs=tre[o<<1|1].rs|mul[tre[o<<1|1].ms][tre[o<<1].rs];
tre[o].ms=mul[tre[o<<1].ms][tre[o<<1|1].ms];
tre[o].all=tre[o<<1].all|tre[o<<1|1].all|mul[tre[o<<1].rs][tre[o<<1|1].ls];
}
void build(int o,int l,int r)
{
tre[o].l=l;
tre[o].r=r;
if(l==r)
{
int x;
scanf("%d",&x);
tre[o].ls=tre[o].rs=tre[o].ms=tre[o].all=1<<root(x);
return;
}
build(lson);
build(rson);
pushup(o);
}
Node query(int o,int x,int y)
{
if(tre[o].l==tre[o].r)
return tre[o];
if(x==tre[o].l && y==tre[o].r)
{
return tre[o];
}
if(x>mid)
return query(o<<1|1,x,y);
else if(y<=mid)
return query(o<<1,x,y);
else
{
Node t1=query(o<<1,x,mid);
Node t2=query(o<<1|1,mid+1,y);
Node t3;
t3.all=t1.all|t2.all|mul[t1.rs][t2.ls];
t3.ls=t1.ls|mul[t1.ms][t2.ls];
t3.rs=t2.rs|mul[t2.ms][t1.rs];
t3.ms=mul[t1.ms][t2.ms];
return t3;
}
}
int main()
{
int T;
init();
scanf("%d",&T);
int cas=0;
while(T--)
{
int n;
scanf("%d",&n);
build(1,1,n);
int m;
scanf("%d",&m);
printf("Case #%d:\n",++cas);
while(m--)
{
int x,y;
scanf("%d%d",&x,&y);
Node ans=query(1,x,y);
queue<int>que;
int num=0;
for(int i=9; i>=0; i--)
if(ans.all&(1<<i))
{
que.push(i);
num++;
if(num==5)
break;
}
while(num<5)
{
que.push(-1);
num++;
}
printf("%d",que.front());
que.pop();
while(!que.empty())
{
printf(" %d",que.front());
que.pop();
}
puts("");
}
if(T)
puts("");
}
return 0;
}