• 题解#1


    表示感觉一题开一篇博文好麻烦啊。。。于是写到一块算了。。。写多了再新开博文

    现在做了几题:

                                                              12

    【BZOJ3529: [Sdoi2014]数表】

    定义f[i]为i的约数之和,g[i]为n,m内gcd=i的数对的个数。那么答案=sigma f[i]*g[i]。

    变换一下发现可以把n,m提出来,变成ans=[n/i]*[m/i]*f[j]*mu[i/j] 其中j|i

    可以把g[i]定义成一个新函数=f[j]*mu[i/j]

    但我们发现计算的时候有a的限制,所以考虑离线操作,将询问按a排序,f[i]也从小到大排序。

    但这样g[i]的值是一直发生改变的。所以我们需要用树状数组来进行单点修改和区间和查询。

     1 struct rec{int x,y,z,id;}a[maxn];
     2 pa b[maxn];
     3 int mm,ret[maxn],mx,s[maxn],tot,p[maxn],mu[maxn],f[maxn];
     4 bool v[maxn];
     5 void get()
     6 {
     7     mu[1]=1;
     8     for2(i,2,mx)
     9     {
    10         if(!v[i])p[++tot]=i,mu[i]=-1;
    11         for1(j,tot)
    12         {
    13             int k=i*p[j];
    14             if(k>mx)break;
    15             v[k]=1;
    16             if(i%p[j])mu[k]=-mu[i];
    17             else {mu[k]=0;break;}
    18         }
    19     }
    20     for1(i,mx)
    21      for(int j=i;j<=mx;j+=i)
    22         f[j]+=i;
    23     for1(i,mx)b[i]=make_pair(f[i],i);
    24     sort(b+1,b+mx+1);
    25 }
    26 inline void add(int x,int y){if(!y)return;for(;x<=mx;x+=x&(-x))s[x]+=y;}
    27 inline int sum(int x){int t=0;for(;x;x-=x&(-x))t+=s[x];return t;}
    28 inline bool cmp(rec a,rec b){return a.z<b.z;}
    29 
    30 int main()
    31 
    32 {
    33 
    34     freopen("input.txt","r",stdin);
    35 
    36     freopen("output.txt","w",stdout);
    37 
    38     mm=read();
    39     for1(i,mm)a[i].x=read(),a[i].y=read(),a[i].z=read(),a[i].id=i,mx=max(mx,max(a[i].x,a[i].y));
    40     get();
    41     sort(a+1,a+mm+1,cmp);
    42     int l=0;
    43     for1(k,mm)
    44     {
    45         int r=upper_bound(b+1,b+mx+1,make_pair(a[k].z+1,-1))-b-1;
    46         for2(i,l+1,r)
    47          for(int j=b[i].second;j<=mx;j+=b[i].second)
    48           add(j,b[i].first*mu[j/b[i].second]);
    49         int n=a[k].x,m=a[k].y,ans=0;
    50         if(n>m)swap(n,m);
    51         for(int i=1,j;i<=n;i=j+1)
    52         {
    53             j=min(n/(n/i),m/(m/i));
    54             ans+=(n/i)*(m/i)*(sum(j)-sum(i-1));
    55         }
    56         ret[a[k].id]=ans;
    57         l=r;
    58     }
    59     for1(i,mm)printf("%d
    ",ret[i]&2147483647);
    60 
    61     return 0;
    62 
    63 }  
    View Code

     【BZOJ3239: Discrete Logging】

    p是素数,裸BSGS。偷懒用了map。hash感觉写起来好麻烦。

     1 map<int,int>mp;
     2 inline int power(int x,int y,int p)
     3 {
     4     int t=1;
     5     for(;y;y>>=1,x=(ll)x*x%p)
     6      if(y&1)t=(ll)t*x%p;
     7     return t;
     8 }
     9 
    10 int main()
    11 
    12 {
    13 
    14     freopen("input.txt","r",stdin);
    15 
    16     freopen("output.txt","w",stdout);
    17     int a,b,p,ans;
    18 
    19     while(scanf("%d%d%d",&p,&a,&b)!=EOF)
    20     {
    21         a%=p;b%=p;
    22         if(!a&&!b)ans=1;
    23         else if(!a)ans=-1;
    24         else  
    25         {
    26             ans=-1;
    27             int m=sqrt(p),t=1;
    28             mp.clear();
    29             mp[1]=m;
    30             for1(i,m-1)
    31             {
    32                 t=(ll)t*a%p;
    33                 if(!mp[t])mp[t]=i;
    34             }
    35             t=(ll)t*a%p;
    36             t=power(t,p-2,p);
    37             for0(i,p/m)
    38             {
    39                 int j=mp[b];
    40                 if(j){ans=j%m+i*m;break;}
    41                 b=(ll)b*t%p;
    42             }
    43         }
    44         if(ans==-1)printf("no solution
    ");else printf("%d
    ",ans);
    45     }
    46 
    47     return 0;
    48 
    49 }  
    View Code

    【BZOJ2956: 模积和】

    逗比题,用总的减去i=j的,随便分块一下就行吧。我是取模狂

     1 ll work(int n)
     2 {
     3     ll ans=0;
     4     for(ll i=1,j;i<=n;i=j+1)
     5     {
     6         j=n/(n/i);
     7         ans=(ans+(ll)n%mod*(j-i+1)%mod-(ll)(n/i)%mod*(i+j)*(j-i+1)/2%mod)%mod;
     8     }
     9     return ans;
    10 }
    11 int main()
    12 {
    13     freopen("input.txt","r",stdin);
    14     freopen("output.txt","w",stdout);
    15     ll n=read(),m=read();
    16     ll ret1=(ll)work(n)*work(m)%mod,ret2=0;
    17     if(n>m)swap(n,m);
    18     for(ll i=1,j;i<=n;i=j+1)
    19     {
    20         j=min(n/(n/i),m/(m/i));
    21         ll t1=(j-i+1)%mod,
    22            t2=(i+j)*(j-i+1)/2%mod,
    23            t3=(j*(j+1)%mod*(2*j+1)%mod-(i-1)*i%mod*(2*i-1)%mod)*inv%mod;
    24         ret2=(ret2+t1*n%mod*m%mod-t2*m%mod*(n/i)%mod-t2*n%mod*(m/i)%mod+t3*(n/i)%mod*(m/i)%mod)%mod;
    25     }
    26     printf("%d
    ",((ret1-ret2)%mod+mod)%mod);
    27     return 0;
    28 }
    View Code

    【BZOJ2257: [Jsoi2009]瓶子和燃料】

    这么水的题都想不出来我可以去死了

    n个数里面挑k个,使gcd最大。暴力分解因数,然后排序,找到最大的在k个数里出现过。

    1000W的sort居然也能过!大概因为因数达不到√n级别吧

     1 int n,m,tot,a[maxn];
     2 int main()
     3 {
     4     freopen("input.txt","r",stdin);
     5     freopen("output.txt","w",stdout);
     6     n=read();m=read();
     7     for1(i,n)
     8     {
     9         int x=read(),y=sqrt(x);
    10         for1(i,y-1)if(x%i==0)
    11         {
    12             a[++tot]=i;
    13             a[++tot]=x/i;
    14         }
    15         if(x%y==0)a[++tot]=y;
    16     }
    17     sort(a+1,a+tot+1);
    18     int cnt=1;
    19     for3(i,tot-1,0)
    20     if(a[i]==a[i+1])cnt++;
    21     else 
    22     {
    23         if(cnt>=m){printf("%d
    ",a[i+1]);break;}
    24         cnt=1;
    25     }    
    26     return 0;
    27 }
    View Code

    【BZOJ2480: Spoj3105 Mod】

    这题太神,另开一篇题解。戳链接:http://www.cnblogs.com/zyfzyf/p/4216095.html

     1 map<int,int>mp;
     2 inline int gcd(int x,int y){return y?gcd(y,x%y):x;}
     3 inline int power(int x,int y,int p)
     4 {
     5     int t=1;
     6     for(;y;y>>=1,x=(ll)x*x%p)
     7      if(y&1)t=(ll)t*x%p;
     8     return t;
     9 }
    10 inline int solve(int a,int b,int c)
    11 {
    12     a%=c;b%=c;
    13     for(int i=0,j=1;i<=50;i++,j=(ll)j*a%c)if(j==b)return i;
    14     int d=0,e=1%c,t;
    15     while((t=gcd(a,c))!=1)
    16     {    
    17         if(b%t)return -1;
    18         c/=t;b/=t;d++;e=(ll)e*a/t%c;
    19     }
    20     mp.clear();
    21     int m=ceil(sqrt(c));
    22     for(int i=0,j=1;i<m;i++,j=(ll)j*a%c)mp[(ll)b*j%c]=i;
    23     a=power(a,m,c);
    24     for(int i=0,j=e;i<=m;i++,j=(ll)j*a%c)
    25      if(i&&mp.find(j)!=mp.end())
    26        return  i*m-mp[j]+d;
    27     return -1;
    28 }
    29 int main()
    30 {
    31     freopen("input.txt","r",stdin);
    32     freopen("output.txt","w",stdout);
    33     while(1)
    34     {
    35         int a=read(),c=read(),b=read(),t;
    36         if(!(a||b||c))break;
    37         if((t=solve(a,b,c))>=0)printf("%d
    ",t);
    38         else printf("No Solution
    ");
    39     }
    40     return 0;
    41 }
    View Code

    【BZOJ1197: [HNOI2006]花仙子的魔法】

    这么神的题我会做?http://vfleaking.blog.163.com/blog/static/174807634201321193348312/

     1 ll f[200][200];
     2 int main()
     3 {
     4     freopen("input.txt","r",stdin);
     5     freopen("output.txt","w",stdout);
     6     int n=read(),m=read();
     7     for1(i,m)f[i][0]=1;
     8     for1(i,n)f[1][i]=i<<1;
     9     for2(i,2,m)
    10      for1(j,n)
    11       f[i][j]=f[i][j-1]+f[i-1][j-1];
    12     cout<<f[m][n]<<endl;
    13     return 0;
    14 }
    View Code

    【BZOJ3122: [Sdoi2013]随机数生成器】

    考虑一般情况,X[n]用等比数列通项求出来,然后就是解a^x=b mod c且c为质数。因为(a,c)=1,所以是裸BSGS。然后再来一堆特判即可。

     1 map<int,int>mp;
     2 inline int power(int x,int y,int p)
     3 {
     4     int t=1;
     5     for(;y;y>>=1,x=(ll)x*x%p)
     6      if(y&1)t=(ll)t*x%p;
     7     return t;
     8 }
     9 inline void exgcd(int a,int b,int &x,int &y)
    10 {
    11     if(!b){x=1;y=0;return;}
    12     exgcd(b,a%b,x,y);
    13     int t=x;x=y;y=t-a/b*y;
    14 }
    15 inline int solve(int a,int b,int c,int p)
    16 {
    17     a=(a%p+p)%p;b=(b%p+p)%p;c=(c%p+p)%p;
    18     int m=ceil(sqrt(p));
    19     mp.clear();
    20     for(int i=0,j=1;i<m;i++,j=(ll)j*a%p)mp[(ll)j*c%p]=i;
    21     a=power(a,m,p);
    22     for(int i=1,j=(ll)b*a%p;i<=m;i++,j=(ll)j*a%p)
    23      if(mp.find(j)!=mp.end())return i*m-mp[j];
    24     return -2;
    25 }
    26 int main()
    27 {
    28     freopen("input.txt","r",stdin);
    29     freopen("output.txt","w",stdout);
    30     int T=read();
    31     while(T--)
    32     {
    33         int p=read(),a=read(),b=read(),x1=read(),t=read();
    34         if(t==x1)printf("%d
    ",1);
    35         else if(a==0)printf("%d
    ",t==x1?1:b==t?2:-1);
    36         else if(a==1)
    37         {
    38             t-=x1;
    39             if(!b){printf("%d
    ",t?-1:1);continue;}
    40             int x,y;
    41             exgcd(b,p,x,y);
    42             x=((ll)x*t%p+p)%p;
    43             printf("%d
    ",x+1);
    44         }else
    45         {
    46             int tmp=(ll)b*power(a-1,p-2,p)%p;
    47             printf("%d
    ",solve(a,x1+tmp,t+tmp,p)+1);
    48         }
    49     }        
    50     return 0;
    51 }
    View Code

    【BZOJ1965: [Ahoi2005]SHUFFLE 洗牌】

    设x为所求答案,令a[i]表示x在第i次洗牌后所在位置,则有a[i]=a[i-1]*2%(n+1) ,然后我们就得到了2^m*x=l mod n+1 解这个同余方程即可。也可以直接一个逆元乘过去,反正gcd=1

     1 ll n,m,l,x,y;
     2 inline ll mul(ll x,ll y,ll p)
     3 {
     4     ll t=0;
     5     for(;y;y>>=1,x=(x+x)%p)
     6      if(y&1)t=(t+x)%p;
     7     return t;
     8 }
     9 ll power(ll x,ll y,ll p)
    10 {
    11     ll t=1;
    12     for(;y;y>>=1,x=mul(x,x,p))
    13      if(y&1)t=mul(t,x,p);
    14     return t;
    15 }
    16 inline void exgcd(ll a,ll b,ll &x,ll &y)
    17 {
    18     if(!b){x=1;y=0;return;}
    19     exgcd(b,a%b,x,y);
    20     ll t=x;x=y;y=t-a/b*y;
    21 }
    22 int main()
    23 {
    24     freopen("input.txt","r",stdin);
    25     freopen("output.txt","w",stdout);
    26     n=read();m=read();l=read();
    27     m=power(2,m,n+1);
    28     exgcd(m,n+1,x,y);
    29     x=(mul(x,l,n+1)+n+1)%(n+1);
    30     cout<<x<<endl;
    31     return 0;
    32 }
    View Code

    【BZOJ3309: DZY Loves Math】

    策爷:

    很容易得到:

    并不是积性函数。
    观察的取值可以发现,

    否则,当时,
    否则,中存在两个质因子的次数不相同,
    上述性质容易通过展开得到证明。(随便yy一下就可以了把)
    这样,在线性筛的同时记录的最小质因子的次数,以及即可。

     1 int a[maxn],b[maxn],mx,tot,p[maxm],f[maxm],g[maxm],s[maxm];
     2 bool v[maxm];
     3 void get()
     4 {
     5     f[1]=1;g[1]=0;
     6     for2(i,2,mx)
     7     {
     8         if(!v[i])
     9         {
    10             p[++tot]=i;
    11             f[i]=i;g[i]=1;s[i]=1;
    12         }
    13         for1(j,tot)
    14         {
    15             int k=i*p[j];
    16             if(k>mx)break;
    17             v[k]=1;
    18             if(i%p[j])
    19             {
    20                 f[k]=p[j];g[k]=1;s[k]=g[i]==1?-s[i]:0;
    21             }else
    22             {
    23                 f[k]=f[i]*p[j];g[k]=g[i]+1;
    24                 int t=i/f[i];
    25                 s[k]=t==1?1:g[t]==g[k]?-s[t]:0;
    26                 break;
    27             }
    28         }
    29     }
    30     for1(i,mx)s[i]+=s[i-1];
    31 }
    32 int main()
    33 {
    34     freopen("input.txt","r",stdin);
    35     freopen("output.txt","w",stdout);
    36     int T=read();
    37     for3(i,T,1)a[i]=read(),b[i]=read(),mx=max(mx,max(a[i],b[i]));
    38     get();
    39     while(T--)
    40     {
    41         int n=a[T+1],m=b[T+1];
    42         if(n>m)swap(n,m);
    43         ll ans=0;
    44         for(int i=1,j;i<=n;i=j+1)
    45         {
    46             j=min(n/(n/i),m/(m/i));
    47             ans+=(ll)(s[j]-s[i-1])*(n/i)*(m/i);
    48         }
    49         printf("%lld
    ",ans);
    50     }    
    51     return 0;
    52 }
    View Code

    【BZOJ 3283: 运算器】

    真是2242的超级加强版啊。。。不过有了前面的基础,这题也是裸题了

    第一问 快速幂 第二问 exbsgs 第三问 组合数取模最终版。

    获得成就:代码最短&&耗时最长(T_T)

    不管了,反正我过了。我用map我自豪!

     1 int tot,cur,cnt,p[maxn],pc[maxn],fac[maxn];
     2 map<int,int>mp;
     3 inline int gcd(int x,int y){return y?gcd(y,x%y):x;}
     4 inline int power(int x,int y,int p)
     5 {
     6     int t=1;
     7     for(;y;y>>=1,x=(ll)x*x%p)
     8         if(y&1)t=(ll)t*x%p;
     9     return t;
    10 }
    11 inline void exgcd(int a,int b,int &x,int &y)
    12 {
    13     if(!b){x=1;y=0;return;}
    14     exgcd(b,a%b,x,y);
    15     int t=x;x=y;y=t-a/b*y;
    16 }
    17 inline int inv(int a,int b)
    18 {
    19     int x,y;
    20     exgcd(a,b,x,y);
    21     return ((x%b)+b)%b;
    22 }
    23 inline int bsgs(int a,int b,int c)
    24 {
    25     a%=c;b%=c;
    26     for(int i=0,j=1;i<=50;i++,j=(ll)j*a%c)if(j==b)return i;
    27     int t,d=0,e=1;
    28     while((t=gcd(a,c))!=1)
    29     {
    30         if(b%t)return -1;
    31         b/=t;c/=t;d++;e=(ll)e*a/t%c;
    32     }
    33     int m=ceil(sqrt(c));
    34     mp.clear();
    35     for(int i=0,j=1;i<m;i++,j=(ll)j*a%c)mp[(ll)b*j%c]=i;
    36     a=power(a,m,c);
    37     for(int i=1,j=(ll)e*a%c;i<=m;i++,j=(ll)j*a%c)
    38         if(mp.find(j)!=mp.end())return i*m-mp[j]+d;
    39     return -1;
    40 }
    41 inline int calc(int n,int p,int pc)
    42 {
    43     if(n<p)return fac[n];
    44     cnt+=cur*n/p;
    45     return (ll)fac[n%pc]*power(fac[pc-1],n/pc,pc)%pc*calc(n/p,p,pc)%pc;
    46 }
    47 inline int solve(int m,int n,int p,int pc)
    48 {
    49     cnt=0;cur=1;
    50     for1(i,pc-1)fac[i]=(ll)fac[i-1]*(i%p?i:1)%pc;
    51     int t1=calc(n,p,pc);
    52     for1(i,pc-1)fac[i]=(ll)fac[i-1]*(i%p?inv(i,pc):1)%pc;
    53     cur=-1;
    54     int t2=(ll)calc(m,p,pc)*calc(n-m,p,pc)%pc;
    55     return (ll)t1*t2%pc*power(p,cnt,pc)%pc;
    56 }
    57 
    58 int main()
    59 
    60 {
    61 
    62     freopen("input.txt","r",stdin);
    63 
    64     freopen("output.txt","w",stdout);
    65 
    66     int T=read();fac[0]=1;
    67     while(T--)
    68     {
    69         int ch=read(),a=read(),b=read(),mod=read(),ans=0;
    70         if(ch==1)ans=power(a,b,mod);
    71         else if(ch==2)ans=bsgs(a,b,mod);
    72         else if(a<=b)
    73         {
    74             tot=0;int t=mod;
    75             for(int i=2;i*i<=mod;i++)if(t%i==0)
    76             {
    77                 p[++tot]=i;pc[tot]=1;
    78                 while(t%i==0)t/=i,pc[tot]*=i;
    79             }
    80             if(t>1)p[++tot]=t,pc[tot]=t;
    81             for1(i,tot)
    82             {
    83                 int t1=solve(a,b,p[i],pc[i]),t2=inv(mod/pc[i],pc[i]);
    84                 ans=(ans+(ll)mod/pc[i]*t2%mod*t1%mod)%mod;
    85             }
    86             ans=(ans%mod+mod)%mod;
    87         }
    88         if(ans<0)printf("Math Error
    ");else printf("%d
    ",ans);
    89     }
    90     return 0;
    91 
    92 }  
    View Code

    【BZOJ2694: Lcm】

    另开博文:http://www.cnblogs.com/zyfzyf/p/4218176.html

     1 int tot,p[maxn],g[maxn];
     2 bool v[maxn];
     3 void get()
     4 {
     5     g[1]=1;
     6     for2(i,2,maxm)
     7     {
     8         if(!v[i])p[++tot]=i,g[i]=i-i*i;
     9         for1(j,tot)
    10         {
    11             int k=i*p[j];
    12             if(k>maxm)break;
    13             v[k]=1;
    14             if(i%p[j])g[k]=g[i]*g[p[j]];
    15             else 
    16             {
    17                 int t=i/p[j];
    18                 if(t%p[j]==0)g[k]=0;
    19                 else g[k]=-g[t]*p[j]*p[j]*p[j];
    20                 break;
    21             }
    22         }
    23     }
    24     for1(i,maxm)g[i]+=g[i-1];
    25 }
    26 inline int sum(int n,int m)
    27 {
    28     return n*(n+1)*m*(m+1)/4;
    29 }
    30 
    31 int main()
    32 
    33 {
    34 
    35     freopen("input.txt","r",stdin);
    36 
    37     freopen("output.txt","w",stdout);
    38     get();
    39 
    40     int T=read();
    41     while(T--)
    42     {
    43         int n=read(),m=read(),ans=0;
    44         if(n>m)swap(n,m);
    45         for(int i=1,j;i<=n;i=j+1)
    46         {
    47             j=min(n/(n/i),m/(m/i));
    48             ans+=sum(n/i,m/i)*(g[j]-g[i-1]);
    49         }
    50         printf("%d
    ",ans&mod);
    51     }
    52 
    53     return 0;
    54 
    55 }  
    View Code

     【BZOJ2763: [JLOI2011]飞行路线】

    刷水愉悦身心。。。分层图spfa,差点被卡T

     1 int n,m,k,s,t,head[maxn],d[maxn][15],tot;
     2 struct edge{int go,next,w;}e[2*maxm];
     3 queue<pa>q;
     4 bool v[maxn][15];
     5 inline void add(int x,int y,int w)
     6 {
     7     e[++tot]=(edge){y,head[x],w};head[x]=tot;
     8     e[++tot]=(edge){x,head[y],w};head[y]=tot;
     9 }
    10 
    11 int main()
    12 
    13 {
    14 
    15     freopen("input.txt","r",stdin);
    16 
    17     freopen("output.txt","w",stdout);
    18 
    19     n=read();m=read();k=read();
    20     s=read()+1;t=read()+1;
    21     for1(i,m)
    22     {
    23         int x=read()+1,y=read()+1,w=read();
    24         add(x,y,w);
    25     }
    26     for1(i,n)for0(j,k)d[i][j]=inf;
    27     d[s][0]=0;
    28     q.push(pa(s,0));
    29     while(!q.empty())
    30     {
    31         int x=q.front().first,z=q.front().second;q.pop();
    32         v[x][z]=0;
    33         for4(i,x)
    34         {
    35             if(d[x][z]+e[i].w<d[y][z])
    36             {
    37                 d[y][z]=d[x][z]+e[i].w;
    38                 if(!v[y][z]){v[y][z]=1;q.push(pa(y,z));}
    39             }
    40             if(d[x][z]<d[y][z+1]&&z<k)
    41             {
    42                 d[y][z+1]=d[x][z];
    43                 if(!v[y][z+1]){v[y][z+1]=1;q.push(pa(y,z+1));}
    44             }
    45         }
    46     }
    47     int ans=inf;
    48     for0(i,k)ans=min(ans,d[t][i]);
    49     cout<<ans<<endl;
    50     return 0;
    51 
    52 }  
    View Code
  • 相关阅读:
    匈牙利算法
    Tabbed Activity = viewpager + fragment ?
    gdb调试多线程多进程
    gdb 调试,当发现程序退出,需要定位程序退出位置时。
    将Linux的信号量sem_t封装成事件对象
    Golang包管理工具govendor的使用&go mod
    go get命令详解
    GoLand生成可执行文件(Windows、Linux)
    Linux下线程pid和tid
    理解Linux的进程,线程,PID,LWP,TID,TGID
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/4213749.html
Copyright © 2020-2023  润新知