zoukankan      html  css  js  c++  java
  • 2019牛客暑期多校训练营(第三场)

    https://ac.nowcoder.com/acm/contest/883/D

    (A(n)) 是由n个1组成的一个整数。

    第一步:把 (A(n)) 表示为 (frac{10^n-1}{9}) (第一步都想不出来)

    那么 (A(n)=0;mod;p) ,当9和p互质的时候,存在一个 (inv9) ,那么原式即 ((10^n-1)*inv9=0;mod;p)

    两边乘9,移项得 (10^n=1;mod;p)

    由欧拉定理,得 (10^n=10^{n;mod;p-1};mod;p)

    即这样的n必定是循环的,取 (p-1) 以内的一个研究

    由费马小定理 (a^{p-1} = 1;mod;p) ,这样的n存在,且 (n=p-1)

    这样,随着n增加,模p的余数必定是循环的,循环节的长度至多为 (p-1) ,那会不会有更短的呢?

    考虑 (d|p-1) ,那么可以变形为 (10^{p-1}=10^{dfrac{p-1}{d}};mod;p)((10^frac{p-1}{d})^{d}=1;mod;p)

    这样最小的循环节必定是 (p-1) 的因数(赛中有发现),(O(sqrt {p})) 枚举d,(O(logd)) 验证其是否是循环节(直接快速幂看看是不是和 (10^0=1;mod;p)一样就可以了)

    目前复杂度(O(sqrt {p} logp))

    找到最小的循环节之后,考虑怎么计数。那当然是要求 (d|n) 的个数,这样的(正整数)n明显在m以内有 (lfloorfrac{m}{d} floor)个。

    但是套上 (n=i^j) 之后呢?猜测和d的质因数分解有关(赛中有发现)。

    考虑i的质因数分解 (i=p_1^{a_1}p_2^{a_2}p_3^{a_3}...p_k^{a_k})

    (i^j=p_1^{ja_1}p_2^{ja_2}p_3^{ja_3}...p_k^{ja_k})

    分解d (d=p_1^{b_1}p_2^{b_2}p_3^{b_3}...p_k^{b_k})

    整除的条件,d是n的因子,则n的各个质因子覆盖d,即 (ja_x>=b_x) 对所有的 (1<=x<=k) 成立。

    最值得学习的技巧来啦:考虑固定住j,那么合法的i满足什么条件才能满足上式呢?是d的每种质因子(p_x),i都至少要有(lceilfrac{b_x}{j} ceil)

    把这个值单独抽出来记为g (g=p_x^{lceilfrac{b_x}{j} ceil}),i要覆盖g,则(g|i),这样的i在n范围内有(lfloorfrac{n}{g} floor)个。

    那么单个j的情况可以遍历d的质因子(分解的复杂度被上面对p的分解吸收,而分解后至多十几种质因子)求出。

    当j变化时也会引起g的变化,具体来说每次j的变化可能会导致一些指数变小,但其实指数的总和至多就30多,也就是可以暴力对j进行统计。

    在j超过最大的(b_x)之后,这样g变成1然后不再改变,以后的i都有n个。

    那么特例为什么有2,3,5呢?首先3和9不互质,不存在这样的inv9,所幸3的倍数的各位数字之和都是3的倍数,考虑固定j=1,那么ans+=n/3,当j=2的时候,分别有1,4,9,16,25,36,一个不严谨的办法是继续ans+=n/3,而j=3的时候,分别是1,8,27,64,125,216,也是ans+=n/3。所以干脆就ans=(n*m)/3。

    当2和5的时候, (10^n = 1;mod;p) 显然不可能成立,因为 (10^n = 0;mod;p) 显然成立。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    int read() {
        char c = getchar();
        while(c < '0' || c > '9')
            c = getchar();
        int x = 0;
        while(c >= '0' && c <= '9') {
            x = (x << 3) + (x << 1) + c - '0';
            c = getchar();
        }
        return x;
    }
    
    int qpow(ll x, int n, int p) {
        ll res = 1;
        while(n) {
            if(n & 1)
                res = res * x % p;
            x = x * x % p;
            n >>= 1;
        }
        return res;
    }
    
    const int INF = 1e9 + 1;
    
    int find_d(int p) {
        int n = p - 1, d = INF;
        for(int i = 1; i * i <= n; ++i) {
            if(n % i == 0) {
                if(qpow(10, i, p) == 1)
                    return i;
    
                if(i * i != n) {
                    if(qpow(10, n / i, p) == 1) {
                        d = min(d, n / i);
                    }
                }
    
            }
        }
        return d;
    }
    
    int pk[50], bk[50], k;
    int factor(int n) {
        int maxbk = 0;
        k = 0;
        for(int i = 2; i * i <= n; ++i) {
            if(n % i == 0) {
                ++k;
                pk[k] = i;
                bk[k] = 0;
                while(n % i == 0) {
                    ++bk[k];
                    n /= i;
                }
                maxbk = max(maxbk, bk[k]);
            }
        }
        if(n != 1) {
            ++k;
            pk[k] = n;
            bk[k] = 1;
            maxbk = max(maxbk, bk[k]);
        }
        return maxbk;
    }
    
    ll solve(int p, int n, int m) {
    
        int d = find_d(p);
        if(d == INF)
            return 0;
        int maxbk = factor(d);
    
        ll ans = 0;
        for(int j = 1; j <= m; ++j) {
            int g = 1;
            for(int i = 1; i <= k; ++i) {
                g = g * qpow(pk[i], (bk[i] + j - 1) / j, p);
            }
            ans += n / g;
            if(j >= maxbk) {
                ans += 1ll * (m - j) * (n / g);
                return ans;
            }
        }
        return ans;
    }
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        int T = read();
        while(T--) {
            int p = read(), n = read(), m = read();
            ll ans = 0;
            switch(p) {
            case 3:
                ans = 1ll * (n / 3) * m;
                break;
            case 2:
                break;
            case 5:
                break;
            default:
                ans = solve(p, n, m);
            }
            printf("%lld
    ", ans);
        }
    }
    

    既然有dalao喜欢开源模板……
    https://ac.nowcoder.com/acm/contest/view-submission?submissionId=40924149

    include <bits/stdc++.h>
    using namespace std;
    #define rep(i,a,n) for (int i=a;i<n;i++)
    #define per(i,a,n) for (int i=n-1;i>=a;i--)
    #define pb push_back
    #define mp make_pair
    #define all(x) (x).begin(),(x).end()
    #define fi first
    #define se second
    #define SZ(x) ((int)(x).size())
    typedef vector<int> VI;
    typedef long long ll;
    typedef pair<int,int> PII;
    mt19937 mrand(random_device{}());
    const ll mod=1000000007;
    int rnd(int x) { return mrand() % x;}
    ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
    ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
    // head
     
    typedef pair<ll,ll> PLL;
    namespace Factor {
        const int N=1010000;
        ll C,fac[10010],n,mut,a[1001000];
        int T,cnt,i,l,prime[N],p[N],psize,_cnt;
        ll _e[100],_pr[100];
        vector<ll> d;
        inline ll mul(ll a,ll b,ll p) {
            if (p<=1000000000) return a*b%p;
            else if (p<=1000000000000ll) return (((a*(b>>20)%p)<<20)+(a*(b&((1<<20)-1))))%p;
            else {
                ll d=(ll)floor(a*(long double)b/p+0.5);
                ll ret=(a*b-d*p)%p;
                if (ret<0) ret+=p;
                return ret;
            }
        }
        void prime_table(){
            int i,j,tot,t1;
            for (i=1;i<=psize;i++) p[i]=i;
            for (i=2,tot=0;i<=psize;i++){
                if (p[i]==i) prime[++tot]=i;
                for (j=1;j<=tot && (t1=prime[j]*i)<=psize;j++){
                    p[t1]=prime[j];
                    if (i%prime[j]==0) break;
                }
            }
        }
        void init(int ps) {
            psize=ps;
            prime_table();
        }
        ll powl(ll a,ll n,ll p) {
            ll ans=1;
            for (;n;n>>=1) {
                if (n&1) ans=mul(ans,a,p);
                a=mul(a,a,p);
            }
            return ans;
        }
        bool witness(ll a,ll n) {
            int t=0;
            ll u=n-1;
            for (;~u&1;u>>=1) t++;
            ll x=powl(a,u,n),_x=0;
            for (;t;t--) {
                _x=mul(x,x,n);
                if (_x==1 && x!=1 && x!=n-1) return 1;
                x=_x;
            }
            return _x!=1;
        }
        bool miller(ll n) {
            if (n<2) return 0;
            if (n<=psize) return p[n]==n;
            if (~n&1) return 0;
            for (int j=0;j<=7;j++) if (witness(rand()%(n-1)+1,n)) return 0;
            return 1;
        }
        ll gcd(ll a,ll b) {
            ll ret=1;
            while (a!=0) {
                if ((~a&1) && (~b&1)) ret<<=1,a>>=1,b>>=1;
                else if (~a&1) a>>=1; else if (~b&1) b>>=1;
                else {
                    if (a<b) swap(a,b);
                    a-=b;
                }
            }
            return ret*b;
        }
        ll rho(ll n) {
            for (;;) {
                ll X=rand()%n,Y,Z,T=1,*lY=a,*lX=lY;
                int tmp=20;
                C=rand()%10+3;
                X=mul(X,X,n)+C;*(lY++)=X;lX++;
                Y=mul(X,X,n)+C;*(lY++)=Y;
                for(;X!=Y;) {
                    ll t=X-Y+n;
                    Z=mul(T,t,n);
                    if(Z==0) return gcd(T,n);
                    tmp--;
                    if (tmp==0) {
                        tmp=20;
                        Z=gcd(Z,n);
                        if (Z!=1 && Z!=n) return Z;
                    }
                    T=Z;
                    Y=*(lY++)=mul(Y,Y,n)+C;
                    Y=*(lY++)=mul(Y,Y,n)+C;
                    X=*(lX++);
                }
            }
        }
        void _factor(ll n) {
            for (int i=0;i<cnt;i++) {
                if (n%fac[i]==0) n/=fac[i],fac[cnt++]=fac[i];}
            if (n<=psize) {
                for (;n!=1;n/=p[n]) fac[cnt++]=p[n];
                return;
            }
            if (miller(n)) fac[cnt++]=n;
            else {
                ll x=rho(n);
                _factor(x);_factor(n/x);
            }
        }
        void dfs(ll x,int dep) {
            if (dep==_cnt) d.pb(x);
            else {
                dfs(x,dep+1);
                for (int i=1;i<=_e[dep];i++) dfs(x*=_pr[dep],dep+1);
            }
        }
        void norm() {
            sort(fac,fac+cnt);
            _cnt=0;
            rep(i,0,cnt) if (i==0||fac[i]!=fac[i-1]) _pr[_cnt]=fac[i],_e[_cnt++]=1;
                else _e[_cnt-1]++;
        }
        vector<ll> getd() {
            d.clear();
            dfs(1,0);
            return d;
        }
        vector<ll> factor(ll n) {
            cnt=0;
            _factor(n);
            norm();
            return getd();
        }
        vector<PLL> factorG(ll n) {
            cnt=0;
            _factor(n);
            norm();
            vector<PLL> d;
            rep(i,0,_cnt) d.pb(mp(_pr[i],_e[i]));
            return d;
        }
        bool is_primitive(ll a,ll p) {
            assert(miller(p));
            vector<PLL> D=factorG(p-1);
            rep(i,0,SZ(D)) if (powl(a,(p-1)/D[i].fi,p)==1) return 0;
            return 1;
        }
        int findorder(ll a,ll p) {
            assert(miller(p));
            vector<PLL> D=factorG(p-1);
            int t=p-1;
            rep(i,0,SZ(D)) {
                while (t%D[i].fi==0&&powl(a,t/D[i].fi,p)==1) t/=D[i].fi;
            }
            return t;
        }
    }
     
    int _,p;
    ll n,m;
    int main() {
        Factor::init(100000);
        for (scanf("%d",&_);_;_--) {
            scanf("%d%lld%lld",&p,&n,&m);
            if (p==2||p==5) {
                puts("0");
                continue;
            }
            if (p==3) {
                printf("%lld
    ",m*(n/3));
                continue;
            }
            ll x=Factor::findorder(10,p);
            vector<PLL> dd=Factor::factorG(x);
            ll ans=0;
            for (int i=1;i<=m;i++) {
                ll y=1;
                int me=0;
                for (auto q:dd) {
                    int e=(q.se+i-1)/i;
                    me=max(me,e);
                    rep(j,0,e) y=y*q.fi;
                }
                if (me==1) {
                    ans+=(n/y)*(m-i+1);
                    break;
                } else {
                    ans+=n/y;
                }
            }
            printf("%lld
    ",ans);
        }
    }
    
  • 相关阅读:
    $digest / $apply digest in progress报错
    get与post请求
    面试题(北京)
    Docker监控平台prometheus和grafana,监控redis,mysql,docker,服务器信息
    Zabbix系列优秀博文
    Docker安装Zabbix
    使用Docker部署监控系统,Prometheus,Grafana,监控服务器信息及Mysql
    docker镜像加速,docker更换为国内镜像
    记一次,Docker镜像1G多精简至300+M的过程
    docker通过dockerfile构建JDK最小镜像,Docker导出导入镜像
  • 原文地址:https://www.cnblogs.com/Yinku/p/11249564.html
Copyright © 2011-2022 走看看