频道栏目
首页 > 程序开发 > 综合编程 > 其他综合 > 正文
数论 CQOI2017
2017-04-12 13:56:00         来源:LiuJunhao's Blog  
收藏   我要投稿

数论 CQOI2017:输出文件 table.out。输出共m行,每次操作之后输出1行,表示答案mod 1,000,000,007之后的结果。

这样一个傻逼题为什么当时不A
观察式子(a,a+b)可以发现,我们可以根据gcd给表格的元素分组。每次修改一个一个数(i,j),和它同组的元素都会修改。
对于每一组,比如第g组,f(i,j)=f(g,g)?(i/g)?(j/g),第g组的和为S(g) S(g)=f(g,g)×∑i=1?kg?i∑j=1kg[gcd(i,j)]j=f(g,g)×(2×∑i=1?kg?i∑ji[gcd(i,j)]j)=f(g,g)×(2×∑i=1?kg?i×i×?(i)+[i==1]2)=f(g,g)×∑i=1?kg??(i)×i×i
然后考场上我就在第二个等式之后卡住咯。。。
求出f(g,g)的前缀和和phi(i)×i×i的前缀和我们就可以分块优化。由于查询操作是修改操作的n√倍,我们使用分块来维护前缀和,时间复杂度为O(n+m(√n))

代码

#include
#include
#include
template
void Read(T &x){
    char c;
    bool f(0);
    while(c=getchar(),c!=EOF)
        if(c=='-')
            f=1;
        else if(c>='0'&&c<='9'){
            x=c-'0';
            while(c=getchar(),c>='0'&&c<='9')
                x=x*10+c-'0';
            ungetc(c,stdin);
            if(f)
                x=-x;
            return;
        }
}
#define MOD 1000000007
#define MAXN 4000000
int p[MAXN+10],pcnt,sk[MAXN+10],phi[MAXN+10],bl[MAXN+10];
int n,m;
bool f[MAXN+10];
void prepare(){
    int i,j;
    phi[1]=1;
    sk[1]=1;
    for(i=2;i<=n;i++){
        if(!f[i]){
            phi[i]=i-1;
            p[++pcnt]=i;
        }
        for(j=1;i*p[j]<=n;j++){
            f[i*p[j]]=1;
            if(i%p[j]==0){
                phi[i*p[j]]=phi[i]*p[j];
                break;
            }
            phi[i*p[j]]=phi[i]*phi[p[j]];
        }
        sk[i]=(sk[i-1]+1ll*phi[i]*i%MOD*i)%MOD;
    }
}
long long tms[MAXN+10],in[MAXN+10],out[MAXN+10];
int gcd(int a,int b){
    int t;
    while(b){
        t=a%b;
        a=b;
        b=t;
    }
    return a;
}
int lowbit(int x){
    return x&-x;
}
void update(int x,int d){
    for(int i=x;bl[x]==bl[i];i++)
        in[i]+=d;
    for(int i=bl[x]+1;i<=bl[n];i++)
        out[i]+=d;
}
long long get_sum(int x){
    return out[bl[x]]+in[x];
}
void read(){
    Read(m),Read(n);
    int t=sqrt(n);
    for(int i=1;i<=n;i++)
        bl[i]=(i+t-1)/t;
    for(int i=1;i<=n;i++)
        in[i]=in[i-1]+(tms[i]=(1ll*i*i)%MOD);
}
int Sum(int n){
    return 1ll*n*(n+1)/2%MOD;
}
void solve(){
    long long i,a,b,k,d;
    long long x;
    while(m--){
        Read(a),Read(b),Read(x),Read(k);
        d=gcd(a,b);
        update(d,-tms[d]);
        tms[d]=x/(1ll*a*b/d/d)%MOD;

        update(d,tms[d]);
        long long tt;
        long long ans=0;
        for(i=1;i<=k;i=tt+1){
            tt=k/(k/i);
            long long ttt=(get_sum(tt)-get_sum(i-1))%MOD,ret(0);
            ret=sk[k/i];
            ans=((ans+ttt*ret)%MOD+MOD)%MOD;
        }
        printf("%lld\n",ans);
    }
}
int main()
{
    read();
    prepare();
    solve();
}

我辜负了出题人的良苦用心。

点击复制链接 与好友分享!回本站首页
上一篇:整数组顺序使奇数位于偶数前面
下一篇:JEVT 代码分析之主线程main函数分析
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站