|
Category Archives: DefaultCategory
Number (dp-性质数状态表示)
Number
【题目描述】
明明在做力学作业的时候发现一类数非常有趣,他们和杠杆有比较相似的结构。这类数有这样的性质:
把某一位当成支点的话,那么左边的数字到这个点的力矩和等于右边的数字到这个点的力矩和,力矩可以理解为距离乘以数字。
举个例子,4139就是满足条件的数字,把3当成支点,我们有这样的等式4 * 2 + 1 *1 = 9 * 1。
小明想知道在一个区间[x,y]中,有多少个这样的数。
【输入数据】
两个数,表示x,y。 0 <= x,y<= 1018。
【输出数据】
一个输出,表示区间[x,y]中满足条件的数的个数。
【样例输入】
7604 24324
【样例输出】
897
【数据范围】
0 <= x,y<= 1018
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<functional> #include<algorithm> using namespace std; #define MAXS 810 + 10 +4000 #define MAXx 1000000000000000000 #define MAXI 30 long long f[MAXI][MAXS][2],depth,a[MAXI],ans,pos; //0 <= 只能取<=第i位的数,否则超过X越界 1 高位已经取了更小的 位数 后面随便取 long long dfs(int i,int s,int c) { if (s<0||s>MAXS) return 0; if ((i==0)&&((s)||(c))) return 0; if (i==0) {//cout<<i<<' '<<s<<' '<<c<<' '<<f[i][s][c]<<endl; return 1;} // cout<<i<<' '<<s<<' '<<c<<' '<<f[i][s][c]<<endl; if (f[i][s][c]>=0) return f[i][s][c]; else f[i][s][c]=0; if (!c) { // cout<<"push "<<a[i]<<endl; f[i][s][c]+=dfs(i-1,s-(pos-i)*a[i],0); } else { for (int k=0;k<a[i];k++) //{ cout<<"push "<<k<<endl; f[i][s][c]+=dfs(i-1,s-(pos-i)*k,0); // cout<<"pop "<<k<<endl;} for (int k=0;k<=9;k++)//{ cout<<"push "<<k<<endl; f[i][s][c]+=dfs(i-1,s-(pos-i)*k,1); //cout<<"pop "<<k<<endl;} } return f[i][s][c]; } long long calc(long long x) { if (!x) return 0; //<0的杠杆数为0 long long ans=0; memset(f,0,sizeof(f)); depth=0; while (x) { depth++; a[depth]=x%10; x=x/10; } for (int i=1;i<=depth/2;i++) { swap(a[i],a[depth-i+1]); } ans=0; f[depth+1][0][0]=1; // =29333 f[depth+1][0][1]=1; // <29333 for (pos=1;pos<=depth;pos++) { memset(f,128,sizeof(f)); // cout<<f[19][0][0]<<endl; ans+=/*dfs(depth,0,0)+*/dfs(depth,0,1); ans--; //不考虑 0 它无论支点为几都出现 } return ans+1; //最后 加上 0 /* f[i][s][c]=f[i-1][s-(k-i)*j][0] */ } int main() { freopen("number.in","r",stdin); freopen("number.out","w",stdout); long long x,y; scanf("%lld%lld",&x,&y); printf("%lld",calc(y+1)-calc(x)); // while (1); }
POJ 3049(输出字母)
在一堆字母中找一段字母,使其中至少含有1个原音,2个辅音字母,且按字典序从小到大排列
果断搜
Program P3049; var n,i,j,m:longint; a:array[1..26] of char; b:array['a'..'z'] of boolean; c:char; procedure swap(var a,b:char); var t:char; begin t:=a;a:=b;b:=t; end; procedure dfs(father:longint;s:string;flag:boolean;l:longint); var i:longint; begin if l=n then begin if flag then writeln(s); exit; end; for i:=father+1 to m-(n-l)+1 do dfs(i,s+a[i],flag or b[a[i]],l+1); end; begin fillchar(b,sizeof(b),false); b['a']:=true;b['e']:=true;b['i']:=true;b['o']:=true;b['u']:=true; readln(n,m); for i:=1 to m do begin read(a[i]); read(c); end; for i:=1 to m-1 do for j:=i+1 to m do if ord(a[i])>ord(a[j]) then swap(a[i],a[j]); if n<3 then halt; dfs(0,'',false,0); end.
POJ 2456(二分哲学)
这题普通的二分会T…………
法一:只循环60遍,用ans记录答案(见标程)
法二:进行特判,若l+1==r 则 m=(l+r+1) shl 1 否则 m=(l+r) shl 1
Program P2456; const maxd=1000000000; maxn=100000; var n,c,i,j,k:longint; a:array[1..maxn] of longint; procedure sort(l,r:longint); var m,i,k,head,tot,ans:longint; begin for k:=1 to 60 do begin m:=(l+r) shr 1; head:=1;tot:=0; for i:=2 to n do begin if a[i]-a[head]>=m then begin inc(tot); head:=i; end; end; if tot>=c-1 then begin ans:=m; l:=m+1 end else r:=m-1; end; writeln(ans); end; procedure qsort(l,r:longint); var i,j,m,p:longint; begin i:=l; j:=r; m:=a[(l+r) shr 1]; repeat while a[i]<m do inc(i); while a[j]>m do dec(j); if i<=j then begin p:=a[i];a[i]:=a[j];a[j]:=p; inc(i);dec(j); end; until i>j; if l<j then qsort(l,j); if i<r then qsort(i,r); end; begin read(n,c); for i:=1 to n do read(a[i]); qsort(1,n); sort(1,maxd); end.
POJ 3289(高精度乘法)
高精度乘法
Program P3289; const maxn=40000; F=10; type arr=record d:array[1..maxn] of longint; len,doc:longint; end; var r,m:arr; y:longint; i:longint; a,b:arr; function max(a,b:longint):longint; begin if a<b then exit(b) else exit(a); end; procedure multipy(a,b:arr;var c:arr); var i,j,len:longint; begin fillchar(c,sizeof(c),0); c.len:=a.len+b.len; for i:=1 to a.len do for j:=1 to b.len do begin inc(c.d[i+j-1],a.d[i]*b.d[j]); inc(c.d[i+j],c.d[i+j-1] div F); c.d[i+j-1]:=c.d[i+j-1] mod F; end; while (c.d[c.len]=0) and (c.len>1) do dec(c.len); c.doc:=a.doc+b.doc; end; procedure to_arr(doc:longint;var c:arr); var x,i,n:longint; begin read(x); i:=0; while (x>0) do begin inc(i); c.d[i]:=x mod F; x:=x div F; end; c.len:=i; c.doc:=doc; end; Procedure jie(a:arr;x:longint;var c:arr); begin if x=1 then begin c:=a; exit; end; fillchar(c,sizeof(c),0); if (x mod 2=0) then begin jie(a,x div 2,c); multipy(c,c,c); end else begin jie(a,x div 2,c); multipy(c,c,c); multipy(a,c,c); end; end; begin to_arr(2,r); r.len:=3;r.d[3]:=1; to_arr(0,m); read(y); jie(r,y,r); multipy(m,r,m); for i:=m.len downto m.doc+1 do write(m.d[i]); writeln; end.
POJ 2390 (小数高精度乘法)
小数高精度乘法
m*(1+r/100)^y
Program P2390; const maxn=40000; F=10; type arr=record d:array[1..maxn] of longint; len,doc:longint; end; var r,m:arr; y:longint; i:longint; a,b:arr; function max(a,b:longint):longint; begin if a<b then exit(b) else exit(a); end; procedure multipy(a,b:arr;var c:arr); var i,j,len:longint; begin fillchar(c,sizeof(c),0); c.len:=a.len+b.len; for i:=1 to a.len do for j:=1 to b.len do begin inc(c.d[i+j-1],a.d[i]*b.d[j]); inc(c.d[i+j],c.d[i+j-1] div F); c.d[i+j-1]:=c.d[i+j-1] mod F; end; while (c.d[c.len]=0) and (c.len>1) do dec(c.len); c.doc:=a.doc+b.doc; end; procedure to_arr(doc:longint;var c:arr); var x,i,n:longint; begin read(x); i:=0; while (x>0) do begin inc(i); c.d[i]:=x mod F; x:=x div F; end; c.len:=i; c.doc:=doc; end; Procedure jie(a:arr;x:longint;var c:arr); begin if x=1 then begin c:=a; exit; end; fillchar(c,sizeof(c),0); if (x mod 2=0) then begin jie(a,x div 2,c); multipy(c,c,c); end else begin jie(a,x div 2,c); multipy(c,c,c); multipy(a,c,c); end; end; begin to_arr(2,r); r.len:=3;r.d[3]:=1; to_arr(0,m); read(y); jie(r,y,r); multipy(m,r,m); for i:=m.len downto m.doc+1 do write(m.d[i]); writeln; end.
不等数列 (Dp插入e)
【题目描述】
将1到n任意排列,然后在排列的每两个数之间根据他们的大小关系插入“>”和“<”。问在所有排列中,有多少个排列恰好有k个“<”。答案对2012取模。
【输入格式】
第一行2个整数n,k。
【输出格式】
一个整数表示答案。
【样例输入】
5 2
【样例输出】
66
【数据范围】
对于30%的数据:n <= 10
对于100%的数据:k < n <= 1000,
F[i,j]=f[i-1,j](j+1)+f[i-1][j-1](i-j) i表示从1到i的数 j表示小于号个数
插入最大数e后添了一个>
或者一个<的数量
const maxn=1000; var f:array[0..1000,0..1000] of longint; n,i,j,k:longint; begin assign(input,'num.in'); assign(output,'num.out'); reset(input); rewrite(output); read(n,k); if (k>n-1-k) then k:=n-1-k; for i:=1 to n do begin f[i,0]:=1; f[i,i-1]:=1; end; for i:=2 to n do for j:=1 to k do f[i,j]:=(f[i-1,j]*(j+1)+f[i-1,j-1]*(i-j)) mod 2012; writeln(f[i,k]); close(input); close(output); end.
另附 暴搜%30数据的版本
var b:array[1..10] of boolean; f:array[0..10] of longint; n,k,i:longint; procedure dfs(l,x,father:longint); var i:longint; begin if l=n then begin inc(f[x]); exit; end; for i:=1 to n do if not(b[i]) then begin b[i]:=true; if father<i then dfs(l+1,x+1,i) else dfs(l+1,x,i); b[i]:=false; end; end; begin readln(n,k); fillchar(b,sizeof(b),false); fillchar(f,sizeof(f),0); for i:=1 to n do begin b[i]:=true; dfs(1,0,i); b[i]:=false; end; for i:=0 to n-1 do write(f[i],' '); end.
RQNOJ 658(观光公交)
几大注意点:
1.一次使用氦气加速器会把后面分成好几段。
2.我们仅维护end[i],wait[i]恒定,因此需提前让wait[i]=max(wait[i-1],wait[i]);
3.w[i]+w[i+1]+...+w[j],且w恒定,故可预处理sum[i](满足累加性)
#include<cstdio> #include<cstdlib> #include<cmath> #include<string> #include<algorithm> #include<queue> #include<functional> #include<iostream> #define MAXN 1000 +10 #define MAXM 10000 + 10 #define MAXK 100000 + 10 #define MAXD 100 + 10 #define MAXT 100000 + 10 using namespace std; struct man { int t,l,r; }t[MAXM]; struct interval { int l,r,w; }; int n,m,k,ans,d[MAXN+1],wait[MAXN+1],w[MAXN+1],end[MAXN+1],sum[MAXN+1]; bool operator<(const interval a,const interval b) //重载 operator < 的意思 为q做准备 { return a.w<b.w; } priority_queue<interval> q; //priority_queue<Node, vector<Node>, greater<Node> >; 完整的不能用 void push(int l,int r) { bool flag=0; for (int i=l;i<r;i++) if (d[i]) {flag=1;break;} if (!flag) return; int tot=sum[r]-sum[l]; if (!tot) return ; interval now; now.w=tot; now.l=l; now.r=r; q.push(now); // cout <<"add "<< now.l << ' ' << now.r <<' '<< now.w << endl; } int main() { // freopen("qc.in","r",stdin); memset(wait,0,sizeof(wait)); memset(w,0,sizeof(w)); scanf("%d%d%d",&n,&m,&k); for (int i=1;i<=n-1;i++) scanf("%d",&d[i]); for (int i=1;i<=m;i++) { scanf("%d%d%d",&t[i].t,&t[i].l,&t[i].r); wait[t[i].l]=max(wait[t[i].l],t[i].t); w[t[i].r]++; } end[1]=0; for (int i=2;i<=n;i++) end[i]=max(end[i-1],wait[i-1])+d[i-1]; ans=0; for (int i=1;i<=m;i++) ans+=end[t[i].r]-t[i].t; sum[1]=sum[0]=0; for (int i=2;i<=n;i++) {sum[i]=sum[i-1]+w[i]; wait[i]=max(wait[i-1],wait[i]);} // for (int i=0;i<=n;i++) cout<<end[i]<<' '; // cout<<endl; int tot=d[1],head=1; for (int i=2;i<=n;i++) { if (wait[i]>=end[i]) { if (tot) push(head,i); tot=0; head=i; } tot+=d[i]; /* tot+=w[i]*min(1,d[i]); // tot+=w[i]; */ } if (tot) push(head,n); //00 cout<<ans<<endl; //贪心 // sort(t+1,t+m+1,cmp); // 调试 /* while( !q.empty() ){ cout << q.top().l << ' ' << q.top().r <<' '<< q.top().w << endl; q.pop(); } */ /* for (int i=1;i<=n;i++) { cout<<end[i]<<' '; } */ while (k&&!q.empty()) { /* cout<<"/////////"<<endl; for (int i=1;i<=n;i++) { cout<<end[i]<<' '; } cout<<endl; for (int i=1;i<=n;i++) { cout<<wait[i]<<' '; } cout<<endl; */ interval now=q.top(); q.pop(); ans-=now.w; int i=now.l; //000 // cout << now.l << ' ' << now.r <<' '<< now.w << endl; // cout << ans << endl; //000 while (!d[i]) i++; d[i]--; int head=i,tot=0,i2=0; i++; while (i<=now.r/*&&wait[i]<end[i]*/) { // tot+=w[i-1]; end[i]--; //000 // for (int cse=1;cse<=n;cse++) cout<<end[cse]<<','; // cout<<endl; //- // cout<<i<<endl; // cout<<wait[i+1]<<' '<<end[i+1]<<endl; if (wait[i]==end[i]) {push(head,i);head=i;} i++; } i--; if (head!=now.r) push(head,now.r); /* if (i>now.r) {cout<<"smile"<<endl; cout<<'<'<<' '<<i<<' '<<wait[i]<<' '<<end[i]<<' '<<endl;} */ // cout<<"i2:"<<i2<<endl; /* if (i2) i=i2; i--; push(head,i); if (i<now.r) { // if (!d[head]) tot+=w[head]; push(i,now.r); } */ //处理 end[i] 显然最多影响到 now.r k--; } cout<<ans<<'n'; // 调试 /* while( !q.empty() ){ cout << q.top().l << ' ' << q.top().r <<' '<< q.top().w << endl; q.pop(); } for (int i=1;i<=n;i++) { cout<<end[i]<<' '; } */ // while (1); }
POJ 3661(贝茜晨练)
经典Dp,果断记忆化……
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<functional> using namespace std; #define MAXN 10000 + 10 #define MAXM 500 + 10 int f[MAXN][MAXM],n,m,d[MAXN]; int dfs(int i,int j) { if (i==0) return 0; if (f[i][j]) return f[i][j]; if (i&&!j) f[i][j]=dfs(i-1,0); if (j) f[i][j]=dfs(i-1,j-1)+d[i]; else { for (int k=min(i,m);k>0;k--) { f[i][j]=max(f[i][j],dfs(i-k,k)); } } return f[i][j]; } int main() { // freopen("running.in","r",stdin); memset(f,0,sizeof(f)); scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",&d[i]); printf("%dn",dfs(n,0)); // while (1); return 0; }
POJ 3575(计算几何与二分-无尽的小数处理)
这题 写了将近半个月……总是在D各种Bug
总的说来-这题最难应该是在精度处理上
1
1
0 0 1
这组数据过了就说明精度处理差不多了……
Program kingdom; const maxn=100; maxm=100; le=0.000000001; type circle=record x,y,r:double; end; var s:array[1..maxn,1..1000] of circle; n,i,j,k:longint; m:array[1..maxn] of longint; ans:array[1..maxn,1..4] of double; wanted:array[1..maxn] of double; b:array[1..maxn] of boolean; l,r:double; function arccos(cosa:double):double; var sina,tana:double; begin if cosa=0 then exit(pi/2); sina:=sqrt(1-sqr(cosa)); tana:=sina/cosa; exit(arctan(tana)); end; function min(a,b:double):double; begin if a<b then exit(a) else exit(b); end; function max(a,b:double):double; begin if a>b then exit(a) else exit(b); end; function sector(a,r:double):double; begin exit(a*r*r/2); end; function triangle(a,r:double):double; begin exit(sin(a)*r*r/2); end; function inlside(s:circle;l:double):boolean; begin if (s.x-s.r>l) or (abs(s.x-s.r-l)<le) then exit(true) else exit(false); end; function inrside(s:circle;r:double):boolean; begin if (s.x+s.r<r) or (abs(s.x+s.r-r)<le) then exit(true) else exit(false); end; function intarea(s:circle;l,r:double):double; var i,j:longint; a,a2,s1,s2,s3,s4:double; bl,br:boolean; begin if (r<s.x-s.r) or (s.x+s.r<l) then exit(0); if (s.x<=l) then begin a:=arccos((l-s.x)/s.r)*2; if (abs(s.x-l)<le) then s1:=0 else s1:=triangle(a,s.r); s2:=sector(a,s.r); if s.x+s.r>r then begin a:=arccos((r-s.x)/s.r)*2; s3:=sector(a,s.r); s4:=triangle(a,s.r); s2:=s2-(s3-s4); end; exit(s2-s1); end else if (s.x>=r) then begin a:=arccos((s.x-r)/s.r)*2; if (abs(s.x-r)<le) then s1:=0 else s1:=triangle(a,s.r); s2:=sector(a,s.r); if s.x-s.r<l then begin a:=arccos((s.x-l)/s.r)*2; s3:=sector(a,s.r); s4:=triangle(a,s.r); s2:=s2-(s3-s4); end; exit(s2-s1); end else begin bl:=inlside(s,l); br:=inrside(s,r); if bl and br then exit(pi*s.r*s.r); if bl and not(br) then begin a:=arccos((r-s.x)/s.r)*2; s3:=sector(a,s.r)-triangle(a,s.r); exit(pi*s.r*s.r-s3); end; if not(bl) and br then begin a:=arccos((s.x-l)/s.r)*2; s3:=sector(a,s.r)-triangle(a,s.r); exit(pi*s.r*s.r-s3); end; a:=arccos((s.x-l)/s.r)*2; a2:=arccos((r-s.x)/s.r)*2; s1:=sector(2*pi-a-a2,s.r); s2:=triangle(a,s.r)+triangle(a2,s.r); exit(s1+s2); end; end; function place(k:longint;l,r:double):boolean; var tot:double; i,j:longint; begin tot:=0; for j:=1 to m[k] do begin tot:=tot+intarea(s[k,j],l,r); end; // writeln(tot*n,' ',wanted[k]*pi); if (abs(tot*n-wanted[k]*pi)<le) then exit(true); if (tot*n<(wanted[k]*pi)) then exit(false) else exit(true); end; function bsearch(r1,r2:double):double; var m:double; i,j,k,num:longint; flag:boolean; begin for k:=1 to 60 do begin flag:=false; m:=(r1+r2)/2; for i:=1 to n do if not b[i] then begin flag:=flag or place(i,l,m); if flag then begin num:=i; break; end; end; if flag then r2:=m else r1:=m; end; b[num]:=true; ans[num,1]:=l; ans[num,2]:=r1; exit(r1); end; begin { assign(input,'kingdom.in'); reset(input); } r:=-10000; l:=10000; read(n); fillchar(b,sizeof(b),false); fillchar(wanted,sizeof(wanted),0); for i:=1 to n do begin read(m[i]); for j:=1 to m[i] do begin read(s[i,j].x,s[i,j].y,s[i,j].r); // writeln(s[i,j].x,s[i,j].y,s[i,j].r); r:=max(r,s[i,j].x+s[i,j].r); l:=min(l,s[i,j].x-s[i,j].r); wanted[i]:=wanted[i]+sqr(s[i,j].r); end; end; r:=r+1; for i:=1 to n do l:=bsearch(l,r); for i:=1 to n do begin writeln('4'); writeln(ans[i,1]:7:7,' 3000'); writeln(ans[i,1]:7:7,' -3000'); writeln(ans[i,2]:7:7,' -3000'); writeln(ans[i,2]:7:7,' 3000'); end; // close(input); end.