Palindrome Function

来源:互联网 发布:淘宝4钻 编辑:程序博客网 时间:2024/06/15 11:56

题目飞机直达
题目:Palindrome Function
题意:求sigma(f(i,j)),L<=i<=R, l<=j<+r, 2<=l<=36, 1<=L<=R<=1e9; 数据组数可达1e5;
f(i, j)=: j, j进制下i是回文数字,
1, j进制下i不是回文数字.
思路:由于数据组数太大了, 所以考虑得出结果应该不费劲.这说明要么是结论题,要么需要大量的预处理,或者是要用到记忆化什么的.
任意进制下1e9以内的回文数会有多大呢?不可能超过1e5个吧, 因为回文数的半边一定是不相同的数, 那就好办了。可以把所有进制
下的回文数全部构造出来(就枚举一边就行了,想想就知道不会有重复), 然后排个序, 对每个询问每个进制进行两次二分查找
就可以轻松得到答案。

#include <cstdio>#include <vector>#include <algorithm>using namespace std;typedef long long LL;int const maxa=1e9+0.2;int num[100];vector<int> G[40];void init(){    for (int i=1; i<=200000; i++){        //一开始i到100000 Wa了, 改大一些莫名就A了...至今想不明白到100000怎么会漏掉的呢, 如果有同学知道麻烦告知一声        for (int b=2; b<=36; b++){            int p=0, t=i;            while (t>0){                num[p++]=t%b;                t/=b;            }            LL a1=i, a2=i*b+num[0];//a2偶数位,  a1奇数位(最后一个数字只取一次)            for (int j=1; j<p; j++){                a1=a1*b+num[j];                a2=a2*b+num[j];            }            //a1, a2在b进制下一定是回文数            if (a1<=maxa) G[b].push_back(a1);            if (a2<=maxa) G[b].push_back(a2);        }    }    for (int b=2; b<=36; b++) {        sort(G[b].begin(), G[b].end());    }}int main(void){    init();    int T, ca=1, L, R, l, r;    for (scanf("%d", &T); T; T--){        scanf("%d%d%d%d", &L, &R, &l, &r);        LL ans=0;        for (int b=l; b<=r; b++){            int len=upper_bound(G[b].begin(), G[b].end(), R)-lower_bound(G[b].begin(), G[b].end(), L);            //得到b进制下,[L, R]的回文数            ans+=b*len+(R+1-L-len);        }        printf("Case #%d: %I64d\n", ca++, ans);    }    return 0;}
原创粉丝点击