题解#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 }
【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 }
【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 }
【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 }
【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 }
【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 }
【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 }
【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 }
【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 }
【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 }
【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 }
【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 }