zoukankan      html  css  js  c++  java
  • 《Lecxcy and SakuKumo》

    非常好的一个题:

    首先进行化简:$yn! - xn! = xy Rightarrow  yn! - xn! - xy + (n!)^{2} = (n!)^{2} Rightarrow (n!+y)(n!-x) = (n!)^{2}$

    可以看到的是,式子左边是一个完全平方数。

    那么显然式子的左边是它的两个因子,所以我们只需要找出右边的所有因子然后 - 1(因为对于n!的情况,x,y都要为0.这于题目x,y都是正整数冲突)。

    那么为什么对于所有的因子(除n!)都满足x,y都是正整数满足呢。

    因为n! 即为根号因子的分界线,若x,y都是正整数,那么n! + y 和 n! - x 刚好关于这个分界线两边分布,所以满足因子的对称性,肯定满足。

    所以我们求出所有因子的出现次数,然后由唯一分解定理的扩展即可求得总因子数。

    这里我们虽然应该求n! ^ 2的因子,但是我们可以对n!质因子分解,然后看成两个n!,那么每次计算因子个数都加2即可。

    这样操作复杂度显然有点过高,我们可以对询问离线,然后从小到大去分解,这样避免重复分解。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N = 1e6 + 5;
    const int M = 1e7 + 5;
    const LL Mod = 1e9 + 7;
    #define pi acos(-1)
    #define INF 1e18 + 5
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL x = 0,f = 1;char c = getchar();
            while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
            while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
            return x*f;
        }
    }
    using namespace FASTIO;
    
    int prime[N],tot = 0;
    LL cnt[M],ans[N];
    bool vis[M];
    void init() {
        for(int i = 2;i < M;++i) {
            if(!vis[i]) {
                prime[++tot] = i;
            }
            for(int j = 1;j <= tot && prime[j] * i < M;++j) {
                vis[prime[j] * i] = 1;
                if(i % prime[j] == 0) break;
            }
        }
    }
    LL quick_mi(LL a,LL b) {
        LL re = 1;
        while(b) { 
            if(b & 1) re = re * a % Mod;
            a = a * a % Mod;
            b >>= 1;
        }
        return re;
    }
    struct Node{
        int id,num;
    }p[N];
    bool cmp(Node a,Node b) {
        return a.num < b.num;
    }
    int main()
    {
        init();
        int ca;ca = read();
        for(int i = 1;i <= ca;++i) {
            p[i].id = i,p[i].num = read();
        }
        sort(p + 1,p + ca + 1,cmp);
        int pre = 1;
        p[0].id = 0;
        for(int now = 1;now <= ca;++now) {
            if(p[now].num == pre) ans[p[now].id] = ans[p[now - 1].id];
            else {
                for(int i = pre + 1;i <= p[now].num;++i) {
                    if(!vis[i]) {
                        cnt[i] += 2;
                        continue;
                    }
                    int x = i;
                    for(int j = 1;j <= tot && prime[j] <= x;++j) {
                        if(x == 1 || !vis[x]) break;
                        if(x % prime[j] == 0) {
                            while(x % prime[j] == 0) {
                                cnt[prime[j]] += 2;
                                x /= prime[j];
                            }
                        }
                    }
                    if(x != 1) cnt[x] += 2;
                }
                LL ma = 1;
                for(int i = 1;i <= tot;++i) {
                    int x = prime[i];
                    if(x > p[now].num) break;
                    if(cnt[x] == 0) continue;
                    ma = ma * (cnt[x] + 1) % Mod;
                }
                ans[p[now].id] = (ma - 1) * quick_mi(2,Mod - 2) % Mod;
                pre = p[now].num;
            }
        }
        for(int i = 1;i <= ca;++i) printf("%lld
    ",ans[i]);
        system("pause");
        return 0;
    }
    View Code
  • 相关阅读:
    如何评测一个软件工程师的计算机网络知识水平与网络编程技能水平?
    如何评测软件工程知识技能水平
    深入理解TCP协议及其源代码
    Socket与系统调用深度分析
    创新产品的需求分析:未来的图书会是什么样子?
    构建调试Linux内核网络代码的环境MenuOS系统
    Java实现简单网络聊天程序
    适配器模式的探究
    Linux下ss命令的研究
    业务领域建模Domain Modeling
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/14652029.html
Copyright © 2011-2022 走看看