[LA 6601 Teaching Hazard] 数学

来源:互联网 发布:淘宝被降权多久能恢复 编辑:程序博客网 时间:2024/06/13 00:09

题目

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=599&page=show_problem&problem=4612

分析

其实思路就是枚举结尾0的个数,从x开始向上枚举,n只有10万,加上保证解在5 * 10^18之内,因此枚举数量不是很多。

当枚举个数为i个0时,枚举n的质因数,对每个质因数p算出最大的r使得进制b(b % p ^ r == 0 && b % (p ^ (r + 1)) != 0) 末尾有大于等于i个0,记为s

同时算出末尾大于等于i+1个0的个数t,对每个质因数累乘(s - t)。结果记为a。最后答案累加C(a,2)。

代码

#include<cstring>#include<string>#include<cstdio>#include<cstdlib>#include<iostream>#include<cmath>#include<vector>#include<algorithm>#include<queue>using namespace std;#define ll long long#define pf printf#define sf scanf#define Fill(a,b) memset(a,b,sizeof(a))const int N = 100000;bool v[N + 10];ll s[N + 10],t[N + 10];int p[N + 10];int tot,n;int x;int sum[N + 10];void get_prime(){    Fill(v,0);    tot = 0;    for (int i = 2; i <= N; i++)        if (!v[i])        {            p[++tot] = i;            for (int j = i * 2; j <= N; j += i) v[j] = 1;        }}inline int solve(int x,int y){   /* ll sum = 0;ll tp = n;    while (tp > 0ll)    {        sum = sum + tp / x;        tp = tp / x;    }    return sum / y;*/    return sum[x] / y;}inline int get(int x){    int sum = 0;    int tp = n;    while (tp > 0)    {        sum = sum + tp / x;        tp = tp / x;    }    return sum;}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","r",stdout);    get_prime(); //cout<<tot<<endl;    int cas = 0;    while (sf("%d%d",&n,&x) != EOF)    {        //cas++; pf("%d\n",cas);        for (int i = 2; i <= n; i++) sum[i] = get(i);        if (n == 0 && x == 0) break;        ll ans = 0;        while(1)        {            int lim = tot;            for (int i = 1; i <= tot; i++)            {                s[i] = solve(p[i],x);                t[i] = solve(p[i],x + 1);                if (s[i] == 0)                {                    lim = i - 1;                    break;                }            }            if (lim == 0) break;            //break;            ll tmp1 = 1,tmp2 = 1;            for (int i = 1; i <= lim; i++) tmp1 = tmp1 * (s[i] + 1),tmp2 = tmp2 * (t[i] + 1);           // for (int i = 1; i <= lim; i++) cout<<s[i]<<endl;            tmp1 = tmp1 - tmp2;            ans = ans + (tmp1 * (tmp1 - 1)) / 2;            x++;        }        pf("%lld\n",ans);    }    return 0;}


0 0
原创粉丝点击