题解#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\n",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\n");else printf("%d\n",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\n",((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\n",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\n",t);
38         else printf("No Solution\n");
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\n",1);
35         else if(a==0)printf("%d\n",t==x1?1:b==t?2:-1);
36         else if(a==1)
37         {
38             t-=x1;
39             if(!b){printf("%d\n",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\n",x+1);
44         }else
45         {
46             int tmp=(ll)b*power(a-1,p-2,p)%p;
47             printf("%d\n",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\n",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\n");else printf("%d\n",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\n",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

 

posted @ 2015-01-09 16:58  ZYF-ZYF  Views(367)  Comments(1Edit  收藏  举报