zoukankan      html  css  js  c++  java
  • 「解题报告」[luoguP6583]回首过去 (数论分块)

    「解题报告」[luoguP6583]回首过去 (数论分块)

    传送门

    题面

    题意

    给定正整数 (n), 求出有序整数对 ((x,y)) 的个数, 满足 (1le x,y le n)(frac{x}{y}) 可以表示为十进制有限小数.

    数据范围

    (1 le n le 10^{12})


    思路

    (frac{x}{y}) 是十进制有限小数, 则 (frac{y}{gcd(x,y)}) 的质因子只有 (2)(5).

    枚举 (i,j,d) , 表示 (y=2^i5^jcdot d) , 则 (x) 的数量为 (leftlfloor frac{n}{d} ight floor) , 可以数论分块.

    枚举 (d) 的时候, 需要满足 (d) 不能整除 (2)(5) , 所以数论分块的时候要容斥一下.

    因为每 (10) 个数中必定有 (6) 个数是 (2)(5) 的倍数, 所以数论分块的时候先处理整十的部分, 对于剩下的暴力枚举一下即可.


    代码

    #include<bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    ll n,ans,q[400],cnt,tms;
    bool cmp(ll x,ll y){ return x>y; }
    int main(){
        cin>>n;
        ll t2=1;
        while(t2<=n){
    	ll t5=1;
    	while(t2*t5<=n){
    	    q[++cnt]=t2*t5;
    	    t5*=5ll;
    	}
    	t2*=2ll;
        }
        ll sum=0; q[0]=n+1;
        sort(q+1,q+1+cnt,cmp);
        for(int p=1;p<=cnt;p++){
    	for(ll i=n/q[p-1]+1,j;i<=n/q[p];i=j+1){
    	    j=min(n/q[p],n/(n/i));
    	    ll k=(j-i+1)/10,num=4*k;
    	    for(k=i+k*10;k<=j;k++)
    		if(k%2&&k%5) num++;
    	    sum+=num*(n/i);
    	}
    	ans+=sum;
        }
        printf("%lld
    ",ans);
        return 0;
    }	
    
  • 相关阅读:
    Lucene底层原理和优化经验分享(1)-Lucene简介和索引原理
    mysql 索引
    C++ 后台进程 daemon
    Linux进程状态
    实现一个简单的shared_ptr
    [LeetCode] Factorial Trailing Zeroes
    完美转发
    排序
    每天五个java相关面试题(7)--线程篇
    程序员为什么会淡忘?
  • 原文地址:https://www.cnblogs.com/BruceW/p/13149498.html
Copyright © 2011-2022 走看看