noip模拟赛#45
T1:n<=1e6,求最小的区间包含(1,m)的所有数。
=>双指针扫一遍即可
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=1e6+5; const int maxn=2e3+5; const int inf=0x7f7f7f7f; int a[nmax],cnt[maxn]; int main(){ freopen("Exhibit.in","r",stdin);freopen("Exhibit.out","w",stdout); int n=read(),m=read();rep(i,1,n) a[i]=read(); int r=1,sm=0,ans=inf,res; rep(i,1,n){ while(sm<m&&r<=n) { if(++cnt[a[r]]==1) ++sm;++r; }--r; //printf("(%d %d)\n",i,r); if(sm==m){ if(ans>r-i+1) ans=r-i+1,res=i; } else break; if(r==n) break; if(!--cnt[a[i]]) --sm;++r; } printf("%d %d\n",res,res+ans-1); fclose(stdin);fclose(stdout); return 0; } /* 12 5 2 5 3 1 3 2 4 1 1 5 4 3 */
T2:1000*1000的矩阵,求有多少个联通块。内存限制1M
=>懒得写暴力的了。。。正解似乎是并查集。我学的是ccz大爷的压位。就是压三位,其实多压几位也可以,char的范围是[-128,128],然后就可以省下了一大堆空间。。然后ccz大爷写的bfs很好看。。。学了%%%
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) char s[126][1001]; short q[4096][2]; #define push(x,y) ++qr,q[qr&4095][0]=x,q[qr&4095][1]=y,s[x>>3][y]-=(1<<(x&7)) void bfs(int x,int y){ int ql=1,qr=1;q[1][0]=x;q[1][1]=y; while(ql<=qr){ x=q[ql&4095][0],y=q[ql&4095][1];++ql; if(s[(x-1)>>3][y]&(1<<((x-1)&7))) push(x-1,y); if(s[(x+1)>>3][y]&(1<<((x+1)&7))) push(x+1,y); if(s[x>>3][y+1]&(1<<(x&7))) push(x,y+1); if(s[x>>3][y-1]&(1<<(x&7))) push(x,y-1); } } int main(){ freopen("Part.in","r",stdin);freopen("Part.out","w",stdout); int n,u,v,d,tmp,temp;scanf("%d",&n); rep(i,1,n) rep(j,1,n) { scanf("%d",&u),s[i>>3][j]|=(1-u)<<(i&7); //printf("(%d %d):%d\n",i,j,s[i>>3][j]); } int ans=0; rep(i,1,n) rep(j,1,n) if(s[i>>3][j]&(1<<(i&7))) bfs(i,j),++ans; printf("%d\n",ans); fclose(stdin);fclose(stdout); return 0; } /* 5 1 0 0 1 0 0 0 0 0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 0 0 */
T3:给一个数n,将n分解成若干个数的和。求最大的最小公倍数。答案<=1e25;
=>不会写。。。正解是利用一个性质就是2*3>2+3 f[2*3]<f[2+3],所以每一个数必定只含有一个质因子。那么dp一下就可以了,然后再高精度。。
=>然后高精度很少写operator<的时候一直弄错。。。而且100以内的质数表自己手写写错了T_T。。。maya
#include<cstdio> #include<cstring> #include<algorithm> #include<cctype> using namespace std; #define rep(i,s,t) for(ll i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) #define ll long long const int a[]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97}; struct node{ int s[30],n; node(int _n=0){ n=_n;clr(s,0); } node operator*(int k){ node res(n); rep(i,1,n) res.s[i]=s[i]*k; rep(i,1,res.n) if(res.s[i]>=10) res.s[i+1]+=res.s[i]/10,res.s[i]%=10; if(res.s[n+1]) res.n++; for(;res.s[res.n];++res.n) if(res.s[res.n]>=10) { res.s[res.n+1]+=res.s[res.n]/10; res.s[res.n]%=10; }--res.n; return res; } node operator=(int x){ for(n=0;x;x/=10) s[++n]=x%10; return *this; } node operator=(const node&o){ n=o.n; rep(i,1,n) s[i]=o.s[i]; return *this; } bool operator<(const node&o){ if(n<o.n) return 1; if(n>o.n) return 0; dwn(i,n,1){ if(s[i]<o.s[i]) return 1; if(s[i]>o.s[i]) return 0; } return 0; } void write(){ dwn(i,n,1) printf("%d",s[i]);printf("\n"); } }; node f[30][1200]; int main(){ freopen("Lcm.in","r",stdin);freopen("Lcm.out","w",stdout); int n;scanf("%d",&n); rep(i,0,n) f[0][i]=1; rep(i,1,25){ rep(j,a[i],n){ f[i][j]=f[i-1][j]; for(int k=a[i];k<=j;k=k*a[i]) if(f[i][j]<f[i-1][j-k]*k){ f[i][j]=f[i-1][j-k]*k; } } } node ans=0; rep(i,1,25) if(ans<f[i][n]) ans=f[i][n]; ans.write(); fclose(stdin);fclose(stdout); return 0; } /* 30 2 2 3 5 7 11 */