• E 洛谷 P3598 Koishi Loves Number Theory[数论]


    题目描述

    Koishi十分喜欢数论。

    她的朋友Flandre为了检测她和数论是不是真爱,给了她一个问题。

    已知

    给定个数,求取模。

    按照套路,呆萌的Koishi当然假装不会做了,于是她来向你请教这个问题,希望你能在秒内给她答案。

    输入输出格式

    输入格式:

    第一行包含两个整数,接下来一行个整数表示

    输出格式:

    一个整数,表示答案

    输入输出样例

    输入样例#1:
    3 5
    1 2 4 5 0
    输出样例#1:
    44044

    说明

    表示若干个数的最小公倍数

    对于10%的数据:

    对于另外20%的数据:

    对于另外30%的数据:

    对于另外40%的数据:


    标解:

    先列两个结论

    结论1可以考虑辗转相除法证明,结论2可以考虑lcm的积性求质因子贡献,这里不详细展开。

     的范围很大,但它们的  数量很少。开一个map维护每个gcd和它的贡献就没了啊。

    这两个结论怎么想出来啊啊啊啊

    实现上好难,去请教了WerkeyTom_FTD %%%

    就是用个map维护a的每个gcd出现的次数(上-下),加入一个数时,(a[i]+1)++,用a[i]+1与当前map里的gcd求gcd,次数取反就行了,然后更新答案

    这里的x很大,所以一读入先%MOD;WerkeyTom_FTD还提到有可能x-1在MOD意义下没有逆元,可以先全乘MOD然后再做

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #include <map>
    using namespace std;
    typedef long long ll;
    const int N=105,MOD=1e9+7;
    inline ll read(){
        char c=getchar();ll x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    ll x,n,a[N];
    inline ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
    map<ll,ll> mp,t;
    map<ll,ll>::iterator it;
    ll Pow(ll a,ll b){
        ll ans=1;
        for(;b;b>>=1,a=a*a%MOD)
            if(b&1) ans=ans*a%MOD;
        return ans;
    }
    ll Inv(ll a){return Pow(a,MOD-2);}
    ll ans=1;
    void solve(){
        for(int i=1;i<=n;i++){ //printf("hi %d %d
    ",i,a[i]);
            t[a[i]]++;
            ans=ans*(Pow(x,a[i])-1)%MOD;//printf("ans %lld
    ",ans);
            for(it=mp.begin();it!=mp.end();it++){
                ll _x=it->first,_y=it->second;
                t[_x]+=_y;
                ll nx=gcd(_x,a[i]),ny=-_y;
                //printf("lala %d %d   %d %d
    ",_x,_y,nx,ny);
                t[nx]+=ny;
                if(ny>0) ans=ans*Pow( Pow(x,nx)-1, ny)%MOD;
                else ans=ans*Pow( Inv(Pow(x,nx)-1), -ny)%MOD;
                //printf("ans %lld
    ",ans);
            }
            swap(mp,t);t.clear();
        }
        ans=ans*Inv(x-1)%MOD;
        printf("%lld
    ",ans);
    }
    int main(int argc, const char * argv[]) {
        x=read()%MOD;n=read();
        for(int i=1;i<=n;i++) a[i]=read()+1;
        solve();
        return 0;
    }
  • 相关阅读:
    小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_5-9.使用JWT生成用户Token回写客户端
    小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_5-8.用户模块开发之保存微信用户信息
    小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_5-7.授权登录获取微信用户个人信息实战
    小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_5-6.微信扫码登录回调本地域名映射工具Ngrock
    Vmware Briged方式使虚拟机上网
    设置VIM的配色方案
    SecureCRT辅助解决方案
    ARM标准汇编与GNU汇编
    arm:c语言和汇编混合编程
    assert()用法
  • 原文地址:https://www.cnblogs.com/candy99/p/6362470.html
Copyright © 2020-2023  润新知