zoukankan      html  css  js  c++  java
  • bzoj 4815 小Q的表格 —— 反演+分块

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4815

    思路就和这里一样:https://blog.csdn.net/leolyun/article/details/70146612

    不知为何乘逆元就错了,必须直接除...不过题目保证了是整数,所以直接除也没问题;

    然后重新学习了一下分块的简洁写法,就能A了hhh

    代码如下:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    int const xn=4e6+5,mod=1e9+7,base=2000,xb=2005;
    int n,cnt,pri[xn],phi[xn],g[xn],blk[xn],s[xn],pls[xb];
    bool vis[xn];
    ll rd()
    {
      ll ret=0,f=1; char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return f?ret:-ret;
    }
    ll pw(ll a,int b)
    {
      ll ret=1;
      for(;b;b>>=1,a=(a*a)%mod)if(b&1)ret=(ret*a)%mod;
      return ret;
    }
    int upt(int x){while(x>=mod)x-=mod; while(x<0)x+=mod; return x;}
    void init()
    {
      phi[1]=1;
      for(int i=2;i<=n;i++)
        {
          if(!vis[i])pri[++cnt]=i,phi[i]=i-1;
          for(int j=1;j<=cnt&&(ll)i*pri[j]<=n;j++)
        {
          vis[i*pri[j]]=1;
          if(i%pri[j])phi[i*pri[j]]=(ll)phi[i]*(pri[j]-1)%mod;
          else {phi[i*pri[j]]=(ll)phi[i]*pri[j]%mod; break;}
        }
        }
      for(int i=1;i<=n;i++)g[i]=(ll)i*i%mod*phi[i]%mod;
      for(int i=2;i<=n;i++)g[i]=upt(g[i-1]+g[i]);
    }
    void init2()
    {
      for(int i=1;i<=n;i++)blk[i]=(i-1)/base+1;
      for(int i=1;i<=n;i++)s[i]=(s[i-1]+(ll)i*i)%mod;
    }
    void change(int d,ll x)//add x
    {
      for(int i=d;blk[i]==blk[d]&&i<=n;i++)s[i]=upt(s[i]+x);
      for(int i=blk[d]+1;i<=blk[n];i++)pls[i]=upt(pls[i]+x);
    }
    int cal(int ps)
    {
      return upt(pls[blk[ps]]+s[ps]);
    }
    int gcd(int a,int b){return b?gcd(b,a%b):a;}
    int main()
    {
      int m=rd(); n=rd();
      init(); init2(); ll x;
      for(int i=1,a,b,k;i<=m;i++)
        {
          a=rd(); b=rd(); x=rd(); k=rd();
          int d=gcd(a,b); 
          //int t1=(ll)d*pw(a,mod-2)%mod,t2=(ll)d*pw(b,mod-2)%mod;
          ll t=((ll)a/d)*(b/d); x=(x/t)%mod;//
          change(d,upt(x-cal(d)+cal(d-1)));
          //change(d,x*t1%mod*t2%mod);
          int ans=0;
          for(int j=1,nxt;j<=k;j=nxt+1)
        {
          nxt=k/(k/j);
          ans=(ans+(ll)g[k/j]*upt(cal(nxt)-cal(j-1)))%mod;
        }
          printf("%d
    ",ans);
        }
      return 0;
    }
  • 相关阅读:
    HDU 1124 Factorial
    hdu 1690 Bus System
    hdu 1113 Word Amalgamation
    POJ 2482 Stars in Your Window
    hdu 1385 ZOJ 1456 Minimum Transport Cost(经典floyd)
    hdu 1907 John
    VMware 虚拟机 安装 UBuntu 9.10 命令模式转换成窗口模试
    #pragma CODE_SEG __NEAR_SEG NON_BANKED详解
    Ubuntu 下Hadoop 伪分布式 hadoop0.20.2.tar.gz 的安装
    文件拷贝代码以及疑问
  • 原文地址:https://www.cnblogs.com/Zinn/p/10116812.html
Copyright © 2011-2022 走看看