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
  • 相关阅读:
    字典树
    Floyd算法
    迪杰斯特拉算法---单源点最短路径
    二叉树的遍历
    图的遍历
    二叉排序树
    拓扑排序
    开发中框架的发展
    IOC
    JS操作JSON总结
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/14652029.html
Copyright © 2011-2022 走看看