HZOI20190829模拟33题解
题面:https://www.cnblogs.com/Juve/articles/11436771.html
A:春思
我们对a分解质因数,则$a=\prod\limits_p^{p|a}p^k$
所以$a^b=\prod\limits_p^{p|a}p^{k*b}$
所以$ans=\prod\limits_p^{p|a}\sum\limits_{q=0}^{k*b}p^q$
然后等比数列求和
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #define int long long using namespace std; const int MAXN=1e2+5; const int mod=9901; int a,b,num[MAXN],sum=0,ans=1,d[MAXN]; int q_pow(int a,int b,int p){ int res=1; while(b){ if(b&1) (res*=a)%=p; (a*=a)%=p; b>>=1; } return res; } signed main(){ scanf("%lld%lld",&a,&b); for(int i=2;i*i<=a;i++){ if(a%i==0){ d[++sum]=i; while(a%i==0){ num[sum]++; a/=i; } (num[sum]*=b)%=(mod-1); } } if(a>1) d[++sum]=a,num[sum]=b%(mod-1); for(int i=1;i<=sum;i++) (ans*=(q_pow(d[i]%mod,(num[i]+1)%(mod-1),mod)-1+mod)%mod*q_pow((d[i]-1)%mod,mod-2,mod)%mod)%=mod; printf("%lld\n",ans); return 0; }
B:密州盛宴
如果我们统计后缀和,规定1为+1,0为-1,则如果有后缀和小于-1就不合法
如果中间出现了小于-1的情况,就把一个0放到第一的位置,然后把当前位置前的所有数向后移一位
因为我们要找的是操作的最大值,所以把所有数向后移一定是优的
然后统计这样的情况
但其实我们发现,对于上面的方法,扫一遍整个字符串,找出后缀最小值,然后答案就是最小值的相反数减一
然后我们优化这种方法
我们发现有循环的字符串
那么我们在每一个循环的字符串上统计答案
我们知道如果这一段字符串的和大于0,那么我们在第一段的时候更新答案
如果小于0,那么在最后一段更新答案
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define int long long using namespace std; const int MAXN=1e6+5; int n,m,ans,res,cnt=0; char ch[MAXN]; struct node{ int t,sum,len,minn,cnt; }in[MAXN]; signed main(){ while(~scanf("%lld%lld",&n,&m)){ if(n+m==0) break; ans=0x7ffffffffffffff;res=cnt=0; for(int i=1;i<=m;i++){ scanf("%s%lld",ch+1,&in[i].t); in[i].len=strlen(ch+1); in[i].minn=0x7ffffffffffffff; in[i].sum=in[i].cnt=0; for(int j=in[i].len;j>=1;j--){ if(ch[j]=='1') in[i].cnt++; in[i].sum+=(ch[j]=='1'?1:-1); in[i].minn=min(in[i].minn,in[i].sum); } cnt+=in[i].cnt*in[i].t; } if(cnt<n){ puts("-1"); continue; } in[m+1].sum=in[m+1].t=0; for(int i=m;i>=1;i--){ res+=in[i+1].sum*in[i+1].t; if(in[i].sum>=0){ ans=min(ans,res+in[i].minn); }else{ ans=min(ans,res+in[i].sum*(in[i].t-1)+in[i].minn); } } if(ans>=0) puts("0"); else printf("%lld\n",-ans-1); } return 0; }
C:赤壁情
咕咕咕~~
**dp
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<ctime> using namespace std; int n,m,k,now=1,pre=0,bnd[105],base; double ans=0; void print(double a,int k){ if(k==0) printf("%0.0lf\n",a); else if(k==1) printf("%0.1lf\n",a); else if(k==2) printf("%0.2lf\n",a); else if(k==3) printf("%0.3lf\n",a); else if(k==4) printf("%0.4lf\n",a); else if(k==5) printf("%0.5lf\n",a); else if(k==6) printf("%0.6lf\n",a); else if(k==7) printf("%0.7lf\n",a); else if(k==8) printf("%0.8lf\n",a); else if(k==9) printf("%0.9lf\n",a); } double f[2][105][3][15015]; void work1(){ base=7500; f[now][1][0][base-2]=f[now][1][2][base]=1; f[now][1][1][base-1]=2; bnd[1]=1; for(int i=2;i<=n;i++){ now^=1;pre^=1; bnd[i]=min(i,n-i+1); int size=min(7500,i*(i+1)); for(int j=1;j<=bnd[i];j++){ for(int l=-size+base;l<=size+base;l++) for(int k=0;k<=2;k++) f[now][j][k][l]=0; } for(int j=1;j<=bnd[i-1];j++){ for(int l=-size+base;l<=size+base;l++){ f[now][j+1][0][l-i*2]+=f[pre][j][0][l]*(j+1); f[now][j][0][l]+=f[pre][j][0][l]*j*2; f[now][j-1][0][l+i*2]+=f[pre][j][0][l]*(j-1); f[now][j+1][1][l-i]+=f[pre][j][0][l]*2; f[now][j][1][l+i]+=f[pre][j][0][l]*2; f[now][j+1][1][l-2*i]+=f[pre][j][1][l]*j; f[now][j][1][l]+=f[pre][j][1][l]*(j*2-1); f[now][j-1][1][l+2*i]+=f[pre][j][1][l]*(j-1); f[now][j+1][2][l-i]+=f[pre][j][1][l]; f[now][j][2][l+i]+=f[pre][j][1][l]; f[now][j+1][2][l-2*i]+=f[pre][j][2][l]*(j-1); f[now][j][2][l]+=f[pre][j][2][l]*(j*2-2); f[now][j-1][2][l+2*i]+=f[pre][j][2][l]*(j-1); } } } for(int i=m;i<=base;i++) ans+=f[now][1][2][i+base]; for(int i=2;i<=n;i++) ans/=(double)i; print(ans,k); return ; } int floor(__float128 x){ for(int i=9;i>=0;--i){ if(x>=i) return i; } } void print__float128(__float128 x,int ws){ int sta[55];sta[0]=0; for(int i=1;i<=ws;++i){ x*=10; sta[i]=floor(x); x-=floor(x); } x*=10; if(floor(x)>=5) sta[ws]++; for(int i=ws;i;--i){ if(sta[i]==10) sta[i]=0,sta[i-1]++; } printf("%d.",sta[0]); for(int i=1;i<=ws;++i) printf("%d",sta[i]); puts(""); } __float128 dp[2][105][3][15015]; void work2(){ base=2000; dp[now][1][0][base-2]=dp[now][1][2][base]=1; dp[now][1][1][base-1]=2; bnd[1]=1; for(int i=2;i<=n;i++){ now^=1;pre^=1; bnd[i]=min(i,n-i+1); int size=min(2000,i*(i+1)); for(int j=1;j<=bnd[i];j++){ for(int l=-size+base;l<=size+base;l++) for(int k=0;k<=2;k++) dp[now][j][k][l]=0; } for(int j=1;j<=bnd[i-1];j++){ for(int l=-size+base;l<=size+base;l++){ dp[now][j+1][0][l-i*2]+=dp[pre][j][0][l]*(j+1); dp[now][j][0][l]+=dp[pre][j][0][l]*j*2; dp[now][j-1][0][l+i*2]+=dp[pre][j][0][l]*(j-1); dp[now][j+1][1][l-i]+=dp[pre][j][0][l]*2; dp[now][j][1][l+i]+=dp[pre][j][0][l]*2; dp[now][j+1][1][l-2*i]+=dp[pre][j][1][l]*j; dp[now][j][1][l]+=dp[pre][j][1][l]*(j*2-1); dp[now][j-1][1][l+2*i]+=dp[pre][j][1][l]*(j-1); dp[now][j+1][2][l-i]+=dp[pre][j][1][l]; dp[now][j][2][l+i]+=dp[pre][j][1][l]; dp[now][j+1][2][l-2*i]+=dp[pre][j][2][l]*(j-1); dp[now][j][2][l]+=dp[pre][j][2][l]*(j*2-2); dp[now][j-1][2][l+2*i]+=dp[pre][j][2][l]*(j-1); } } } __float128 ans=0; for(int i=m;i<=base;i++) ans+=dp[now][1][2][i+base]; for(int i=2;i<=n;i++) ans/=(__float128)i; print__float128(ans,k); return ; } int main(){ scanf("%d%d%d",&n,&m,&k); if(k<=8) work1(); else work2(); return 0; }