记叙一下当时的比赛情况。
开场2分钟看懂A,3分钟写完交上去,CE,发现没有#include<cstdio
。我好菜啊。
然后10分钟时过掉B的pt,开C
20分钟时来了个提醒:注意B题答案可能为负。
突然想起来B题里有一句话const ll int=1ll<<60
。而
260<3∗1018
,gg。
改完后B只剩897分,于是满怀怨恨地锁了B,发现有个人跟我错的一样,叉了。
52分钟时写完C,wa4。
查了很久无果。
中途发现有一句无用的话if(!e[h[x]].next)return;
接着捡了第二个hack
然后造了棵两个点的树,发现自己挂了。因为此时根的度为1,不会dfs到2号点,改完就AC了。
好像过掉E的比过掉D的多,果断开E。
深夜了,意识很模糊。
这个E是数位DP,而且可能只支持
O(qlogr)
。
首先状压每一位的奇偶性是可行的,但这至少要
O(q∗2b)
显然会挂。
然后就放弃状压的思路,试图只存储出现奇数次的digit的次数。
最后15分钟弃疗,捡到了第3个hack。
赛后去看别人代码,发现状压复杂度是对的!因为总状态数只有
O(b∗logrb∗2b)
,每次不一定要从头算到尾,我好菜啊。
最后因为rating太低,还涨了3rating。
upd:注意dp数组初值不能赋成0,否则对于答案为零的状态起不到记忆化的效果,复杂度就不对了。
#include<cstdio>
#include<cstring>
#include<cctype>
typedef long long ll;
inline char read() {
static const int IN_LEN = 1000000;
static char buf[IN_LEN], *s, *t;
if (s == t) {
t = (s = buf) + fread(buf, 1, IN_LEN, stdin);
if (s == t) return -1;
}
return *s++;
}
template<class T>
inline void read(T &x) {
static bool iosig;
static char c;
for (iosig = false, c = read(); !isdigit(c); c = read()) {
if (c == '-') iosig = true;
if (c == -1) return;
}
for (x = 0; isdigit(c); c = read())
x = (x + (x << 2) << 1) + (c ^ '0');
if (iosig) x = -x;
}
const int OUT_LEN = 10000000;
char obuf[OUT_LEN], *oh = obuf;
inline void print(char c) {
if (oh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), oh = obuf;
*oh++ = c;
}
template<class T>
inline void print(T x) {
static int buf[30], cnt;
if (x == 0) {
print('0');
} else {
if (x < 0) print('-'), x = -x;
for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48;
while (cnt) print((char)buf[cnt--]);
}
}
inline void flush() {
fwrite(obuf, 1, oh - obuf, stdout);
}
const int N=5000;
int q,b,cnt[5000],w,a[70];
ll l,r,f[12][70][(1<<11)+5];
ll dfs(int x,int s,bool zero,bool limit){
if(cnt[s]>x)return 0;
if(!x)return 1;
if(~f[b][x][s] && !zero && !limit)return f[b][x][s];
ll ans=0;int i=1,up=limit?a[x]:b;
if(limit && x>1)ans=dfs(x-1,s^(1<<a[x]),0,1);
for(i=zero;i<up;++i)ans+=dfs(x-1,s^(1<<i),0,0);
if(!zero && !limit)f[b][x][s]=ans;
return ans;
}
inline ll calc(ll x){
register ll t=x,ans;register int i;
for(w=0;t;t/=b)a[++w]=t%b;ans=dfs(w,0,1,1);
for(i=w-1;i;--i)
ans+=dfs(i,0,1,0);
return ans;
}
int main(){
//freopen("1.txt","r",stdin);
memset(f,-1,sizeof f);
register int i=1;
for(;i<N;++i)cnt[i]=cnt[i>>1]+(i&1);
read(q);
while(q--){
read(b),read(l),read(r);
print(calc(r+1)-calc(l)),print('\n');
}
flush();
return 0;
}