zoukankan      html  css  js  c++  java
  • 17.10.10

    • 上午
      • 模拟考试(大悲催…)
        • Prob.1(WA

          一个套路,没做过真的好难想出来

          简化题目:

          对于一个整数序列,把任意一个元素修改为任意一个整数为一次操作,问最少需要几次操作可以使得序列(严格)单调上升。

          开始想的是求一个LIS(最长上升子序列),然后发现不对,因为只能修改为整数。

          然后就想不出来了,555

          正解:

          把序列的每个元素的值减去该元素的标号,即a[ i ]-=i ;

          然后再求一个最长不下降子序列,这样求出来的最长序列可以保证:在该最长不下降子序列中的元素不修改的情况下,其他元素一定可以修改成功。

          代码:

          #include<cstdio>
          #include<cstring>
          #include<iostream>
          #include<algorithm>
          using namespace std;
          int lson[100005],rson[100005],key[100005],t[100005],now[100005];
          int n,cnt;
          void DFS(int u){
          	if(lson[u]) DFS(lson[u]);
          	++cnt; t[cnt]=key[u]-cnt;
          	if(rson[u]) DFS(rson[u]);
          }
          void LIS(){
          	cnt=0;
          	for(int i=1;i<=n;i++){
          		if(!cnt||now[cnt]<=t[i]){
          			now[++cnt]=t[i];
          		}
          		else{
          			int l=upper_bound(now+1,now+cnt+1,t[i])-now;
          			now[l]=t[i];
          		}
          	}
          	printf("%d",n-cnt);
          }
          int main(){
          	freopen("binary.in","r",stdin);
          	freopen("binary.out","w",stdout);
          	scanf("%d",&n);
          	for(int i=1;i<=n;i++) scanf("%d",&key[i]);
          	for(int i=2,a,b;i<=n;i++){
          		scanf("%d%d",&a,&b);
          		if(!b) lson[a]=i;
          		else rson[a]=i;
          	}
          	DFS(1);
          	LIS();
          	return 0;
          }
          
    • Prob.2(AC

      一个小技巧:一个序列区间的gcd如果等于该区间的最小值,那么这个区间的所有数都可以被该最小值整除。

      本题两个ST表维护

    • Prob.3(WA

      image

      神题,记忆化搜索

      (S->P)反向考虑交换操作,如果最后一次交换的是a[i]和a[i+1],那么必然在该次交换之前,a[l]~a[i]的值都小于a[i+1]~a[r]。

      所以对于每个成立的a[i],a[i+1],可以把序列分为两段(左一段右一段),然后递归做相同操作。

      然后回溯时对当前递归层的答案贡献

      =左段的方案数*右段的方案数*C(r-l-1,i-l),这个组合数考虑两边的交换顺序

      代码:

      
      
       1 #include<cstdio>
       2 #include<cstring>
       3 #include<iostream>
       4 using namespace std;
       5 const int mod=1000000007;
       6 int dp[55][55],fac[55],inv[55];
       7 int aa[55],pos[55];
       8 int power(int a,int b)
       9 {
      10     int val=1;
      11     while(b)
      12     {
      13         if(b&1) val=(1ll*val*a)%mod;
      14         a=(1ll*a*a)%mod; b>>=1; 
      15     }
      16     return val;
      17 }
      18 void pre_fac_inv(int n)
      19 {
      20     fac[0]=fac[1]=1;
      21     for(int i=2;i<=n;i++) fac[i]=(1ll*fac[i-1]*i)%mod;
      22     inv[n]=power(fac[n],mod-2);
      23     for(int i=n;i>1;i--) inv[i-1]=(1ll*inv[i]*i)%mod;
      24     inv[0]=inv[1];
      25 }
      26 int C(int m,int n)
      27 {
      28     return 1ll*fac[m]*inv[m-n]%mod*inv[n]%mod;
      29 }
      30 int dfs(int l,int r){
      31     if(l>=r) return 1;
      32     if(dp[l][r]) return dp[l][r];
      33     int maxx[55],minn[55];
      34     memset(maxx,0,sizeof(maxx));
      35     memset(minn,0x3f,sizeof(minn));
      36     int ret=0,numl,numr,ma,mi;
      37     for(int i=l;i<=r;i++){
      38         maxx[i]=aa[i];
      39         if(i!=l) maxx[i]=max(maxx[i],maxx[i-1]);
      40     }
      41     for(int i=r;i>=l;i--){
      42         minn[i]=min(minn[i],aa[i]);
      43         if(i!=r) minn[i]=min(minn[i],minn[i+1]);
      44     }
      45     for(int i=l;i<r;i++){
      46         swap(aa[i],aa[i+1]);
      47         ma=max(maxx[i-1],aa[i]);
      48         mi=min(minn[i+2],aa[i+1]);
      49         if(ma<mi){
      50             numl=dfs(l,i);
      51             numr=dfs(i+1,r);
      52             ret=(1ll*ret+1ll*numl*numr%mod*C(r-l-1,i-l)%mod)%mod;
      53         }
      54         swap(aa[i],aa[i+1]);    
      55     }
      56     return dp[l][r]=ret;
      57 }
      58 int main(){
      59     freopen("swap.in","r",stdin);
      60     freopen("swap.out","w",stdout);
      61     int n;
      62     scanf("%d",&n);
      63     pre_fac_inv(n);
      64     for(int i=1;i<=n;i++) scanf("%d",&aa[i]),aa[i]++;
      65     int ans=dfs(1,n);
      66     printf("%d",ans);
      67     return 0;
      68 }
      View Code
      
      
      
      
      
    • 下午
      • 先改了上午的题
      • 然后绝望的发现入门OJ上的题做不了了!!!
      • 就先把前几天做的12道题的题解贴上。
        • 入门OJ 2036 [Noip模拟题]集合贪心
          将每个数x化为 x=a*(k^b) (a%k!=0) 的形式
          对所有的a排序+离散化
          然后排序x后,从小到大去取,
          取的条件为:当前数的b,与之前取的a与当前数的a相同的且b值最大的那个数的b 差值不为1
          (有点绕,分开描述)
          当前数 x=a1*(k^b)
          之前的那个数 x'=a1*(k^b'),且那个数在这个a1的前提下,b'为最大
          如果 b!=b'+1 则可以取
        代码:
        #include<cstdio>
        #include<cstring>
        #include<iostream>
        #include<algorithm>
        #define ll long long
        using namespace std;
        ll a[100005],c[100005],d[100005],tmp;
        int n,k,m,sub,ans,cnt;
        int main(){
        	scanf("%d%d",&n,&k);
        	for(int i=1;i<=n;i++){
        		scanf("%lld",&a[i]); tmp=a[i];
        		while(tmp%k==0) tmp/=k;
        		c[++m]=tmp;
        	}
        	sort(a+1,a+n+1);
        	sort(c+1,c+m+1); m=unique(c+1,c+m+1)-c-1;
        	for(int i=1;i<=n;i++){
        		tmp=a[i]; cnt=0;
        		while(tmp%k==0) tmp/=k,cnt++;cnt++;
        		sub=lower_bound(c+1,c+m+1,tmp)-c;
        		if(!d[sub]||d[sub]!=cnt-1) ans++,d[sub]=cnt;
        	}	
        	printf("%d",ans);
        	return 0;
        }
        • 入门OJ 2075 [Noip模拟题]调整

          建图:
          首先明确一个观点:
          如果我们把一些边调整为边权为0,
          且计算出起点到终点的最短路值小于等于c
          那么一定可以通过让最短路径上调整过的某些边的边权增加,
          (即一开始就把不把其边权变为0),使得该路径的权值和恰好为c
             
          然后就建一个类似层次图的东西
          第几个层次就表示调整了几条边的权值为0
          对于输入的 u,v,w
          对每个层次 u->v 建边权为w的边
          对每个层次的u->下一个层次的v建一个边权为0的边,经过这条边的话就表示要调整其边权为0
             
          最后从小到大枚举每个层次,若该层次的n号节点的dis<=c,那么该层次就是答案(即调整该层次的序号那么多次)
             
          ...不知为何
          用优先队列优化过的spfa跑得还没有裸的spfa快

          代码:

          #include<queue>
          #include<iostream>
          #include<cstdio>
          #include<cstring>
          using namespace std;
          struct edge{
          	int to,val,next;
          }e[3000000];
          int head[200000],dis[200000];
          bool inq[200000];
          int n,m,c,ent=1;
          void add(int u,int v,int w){
          	e[ent]=(edge){v,w,head[u]};
          	head[u]=ent++;
          }
          void spfa(){
          	memset(dis,0x3f,sizeof(dis));
          	queue<int> q;int u,v;
          	q.push(1);inq[1]=1;dis[1]=0;
          	while(!q.empty()){
          		u=q.front(); q.pop(); inq[u]=0;
          		for(int i=head[u];i;i=e[i].next){
          			v=e[i].to;
          			if(dis[v]<=dis[u]+e[i].val) continue;
          			dis[v]=dis[u]+e[i].val;
          			if(inq[v]) continue;
          			q.push(v);
          			inq[v]=1;
          		}
          	}
          }
          int main(){
          	scanf("%d%d%d",&n,&m,&c);
          	for(int i=1,u,v,w;i<=m;i++){
          		scanf("%d%d%d",&u,&v,&w);
          		for(int j=0;j<=m;j++){
          			add(u+j*n,v+j*n,w);
          			add(u+j*n,v+(j+1)*n,0);
          		}
          	}
          	spfa();
          	for(int i=0;i<=m;i++)
          		if(dis[n+i*n]<=c){
          			printf("%d",i);
          			break;
          		}
          	return 0;
          }
    • 入门OJ 2076 [Noip模拟题]集合

      因为A,B的差值不大于10^6,所以不存在两个数可以靠大于10^6的素数合并
      筛出10^6以内的素数,在筛的同时,用并查集合并。

      代码

      #include<iostream>
      #include<cstdio>
      #include<cstring>
      #define ll long long
      using namespace std;
      ll MAXN=1000000;
      ll prime[1000006],fa[2000006];
      bool np[1000006];
      ll ff,ans,A,B,P,cnt;
      ll find(ll x){
      	return fa[x]==x?x:fa[x]=find(fa[x]);
      }
      void find_and_work(){
      	for(int i=1;i<=B-A+1;i++) fa[i]=i;
      	
      	for(ll i=2;i<=MAXN;i++){
      		if(!np[i]){
      			prime[++cnt]=i;
      			if(i>=P){
      				ff=0;
      				for(ll j=((A-1)/i+1)*i;j<=B;j+=i){
      					int f=find(j-A+1);
      					if(!ff) ff=f;
      					else fa[f]=ff;
      				}
      			}
      		}
      		for(ll j=1;j<=cnt&&prime[j]<=MAXN/i;j++){
      			np[i*prime[j]]=1;
      			if(i%prime[j]==0) break;
      		}
      	}
      }
      
      int main(){
      	scanf("%lld%lld%lld",&A,&B,&P);
      	MAXN=min(MAXN,B);
      	find_and_work();
      	for(ll i=1;i<=B-A+1;i++) if(find(i)==i) ans++;
      	printf("%lld",ans);
      	return 0;
      }
    • 入门OJ 2077 [Noip模拟题]购买

      按c排序后模拟即可

      代码

      #include<iostream>
      #include<cstdio>
      #include<cstring>
      #include<algorithm>
      #define ll long long
      using namespace std;
      struct goods{
      	ll k,c;
      	bool operator <(const goods &rtm) const{
      		return c<rtm.c;
      	}
      }g[105];
      ll n,b=1,m,ans,t;
      int main(){
      	scanf("%lld",&n);
      	for(ll i=1;i<=n;i++) scanf("%lld%lld",&g[i].k,&g[i].c);
      	sort(g+1,g+n+1);
      	scanf("%lld",&t);
      	ll i=1;
      	for(ll j=1,x=0,y=0,z=0;j<=t;j++){
      		scanf("%lld",&x);z=y; y=x; x=x-z;
      		while(x&&i<=n){
      			while(g[i].k<=x&&i<=n){
      				ans+=g[i].k*g[i].c*j;
      				x-=g[i].k;
      				i++;
      			}
      			if(i<=n){
      			ans+=x*g[i].c*j;
      			g[i].k-=x;
      			x=0;
      			}
      		}
      	}
      	while(i<=n){
      		ans+=g[i].k*g[i].c*(t+1);
      		i++;
      	}
      	printf("%lld",ans);
      	return 0;
      }
      
    • 入门OJ 2078 [Noip模拟题]填充棋盘

      看题解吧(看不到了诶)
      神奇组合题。

      代码

      #include<cstdio>
      #include<cstring>
      #include<iostream>
      using namespace std;
      const int mod=1000000007;
      int n,m,ans;
      int pow(int a,int b){
      	int val=1;
      	while(b){
      		if(b&1) val=1ll*val*a%mod;
      		a=1ll*a*a%mod;
      		b>>=1;
      	}
      	return val;
      }
      int main(){
      	scanf("%d%d",&n,&m);
      	ans=(1ll*6*(1ll*pow(2,n)+1ll*pow(2,m))-24)%mod;
      	printf("%d",ans);
      	return 0;
      }
      
    • 入门OJ 2081 [Noip模拟题]画山

      dp(背包+递推) 好题

      定义dp[i][j]表示终点在(i,j)的方法数,
      然后每次枚举线段,从前面转移过来:
      dp[i][j]+=dp[i-a],[j-b]
      显然有重复呢。
       
      为了去重,把斜率加入dp状态,
      dp[i][j][k]:表示终点在(i,j)时,且到达改点用的是斜率编号为k的线段。
      目的是每次转移时不能从相同的k转移
      此时,就不能类同上面一样枚举每个线段来转移,(否则会少记录方案)
      而是应该先预处理,把相同斜率的线段归为一组,然后对每一组跑一个物品无限的背包,
      计算出该斜率下可以延伸多长
      然后dp时,枚举每一组斜率,然后枚举背包跑出的可以到达的距离,然后转移。

      O(N*N*M*P)

      代码:

      #include<cstdio>
      #include<cstring>
      #include<iostream>
      #include<algorithm>
      #define ll long long
      using namespace std;
      const ll mod=1000000007;
      struct segment{
      	int a,b;
      	bool operator <(const segment &rtm) const{
      		return b*rtm.a<rtm.b*a;
      	}
      }seg[105];
      struct group{
      	int a,b;
      	bool can[105];
      }gro[105];
      ll dp[105][105][105],s[105][105];
      int gnt,n,m,p;
      int main(){
      	scanf("%d%d%d",&n,&m,&p);
      	for(int i=1;i<=p;i++) scanf("%d%d",&seg[i].a,&seg[i].b);
      	sort(seg+1,seg+p+1);
      	int st=1; bool *f;
      	for(int I=1;I<=p+1;I++){
      		if(I==p+1||(seg[I].b*seg[st].a!=seg[I].a*seg[st].b)){
      			++gnt;
      			gro[gnt].a=seg[st].a; 
      			gro[gnt].b=seg[st].b;
      			f=gro[gnt].can; f[0]=1;
      			for(int i=st;i<I;i++)
      				for(int j=seg[i].a;j<=n;j++)
      					f[j]=f[j]|f[j-seg[i].a];
      			st=I;
      		}
      	}
      	s[0][0]=1;
      	for(int i=0;i<=n;i++)
      		for(int j=0;j<=m;j++)
      			for(int k=1;k<=gnt;k++){
      				for(int o=1;o<=n;o++) if(gro[k].can[o]){
      					int ii=o,jj=ii*gro[k].b/gro[k].a;
      					if(i-ii<0||j-jj<0||j-jj>m) break;
      					dp[i][j][k]=(dp[i][j][k]+s[i-ii][j-jj]-dp[i-ii][j-jj][k]+mod)%mod;
      				}
      				s[i][j]=(s[i][j]+dp[i][j][k]+mod)%mod;
      			}
      	printf("%lld",s[n][0]);
      	return 0;
      }
      
    • 入门OJ 2082 [Noip模拟题]益智游戏

      益智好题
         
      可以明确的是两个人如果会走到相同的一些点,那么这些点一定是连续的
      (都是走最短路嘛)
         
      对于每个人,求出他的最短路DAG图(最短路不止一条啦)
         
      怎么求这个对短路DAG图呢?
      对起点和终点分别跑一次最短路,得到两个dis数组(dis1是从起点跑得,dis2是从终点跑的)
      对于一条边的 u v w,若dis1[u]+dis2[v]+w==dis(起点->终点),那么这条边就在最短路DAG中
         
      然后呢,取出两个人的最短路DAG图中都走的边构成一个新图
      对新图按按拓扑序进行最长路dp。
         
      特判两个人的最短路DAG图是否有相交,
      相交的话,答案要加一,因为dp值是最长路,而要求的是点数
      不相交的话,就不用加了,因为ans本来就等于0;

      代码:

      #include<queue> 
      #include<cstdio>
      #include<cstring>
      #include<iostream>
      #define INF 0x3f3f3f3f3f3f3f3f
      #define ll long long
      #define node(a,b) (node){a,b}
      using namespace std;
      struct node{
      	ll id,d;
      	bool operator <(const node &rtm) const{
      		return d>rtm.d;
      	}
      };
      struct edge{
      	ll from,to,val,next; 
      }e1[200005],e2[200005],e3[200005];
      ll head1[50005],head2[50005],head3[50005];
      ll dis1[50005],dis2[50005],dis3[50005],in[50005];
      bool fg[50005],ve[200005],xj;
      ll n,m,A,B,C,D,ent1=1,ent2=1,ent3=1,disab,discd,ans;
      void add(ll u,ll v,ll w,ll *head,edge *e,ll &ent){
      	e[ent]=(edge){u,v,w,head[u]}; head[u]=ent++;
      }
      ll dijistra(ll st,ll ed,ll *head,ll *dis,edge *e){
      	static bool vis[50005]; 
      	memset(vis,0,sizeof(bool)*(n+3));
      	memset(dis,0x3f,sizeof(ll)*(n+3));
      	priority_queue<node>q; node now; 
      	ll u,v; dis[st]=0;
      	q.push(node(st,0)); 
      	while(!q.empty()){
      		now=q.top(); q.pop(); u=now.id;
      		if(vis[u]) continue; vis[u]=1;
      		for(ll i=head[u];i;i=e[i].next){
      			v=e[i].to;
      			if(vis[v]||dis[v]<=dis[u]+e[i].val) continue;
      			dis[v]=dis[u]+e[i].val;
      			q.push(node(v,dis[v]));
      		}
      	}
      	return dis[ed];
      }
      void topo(ll st,ll ed,ll *head,ll *dis,edge *e){
      	queue<int>q;
      	for(int i=1;i<=n;i++) if(!in[i]) q.push(i);
      	while(!q.empty()){
      		int u=q.front(); q.pop();
      		ans=max(ans,dis[u]);
      		for(int i=head[u];i;i=e[i].next){
      			int v=e[i].to;
      			dis[v]=max(dis[v],dis[u]+1);
      			in[v]--;
      			if(!in[v])q.push(v);
      		}
      	}
      }
      int main(){
      	//freopen("in.in","r",stdin);
      	scanf("%lld%lld",&n,&m);
      	for(ll i=1,a,b,c;i<=m;i++){
      		scanf("%lld%lld%lld",&a,&b,&c);
      		add(a,b,c,head1,e1,ent1);
      		add(b,a,c,head2,e2,ent2);
      	}
      	scanf("%lld%lld%lld%lld",&A,&B,&C,&D);
      	disab=dijistra(A,B,head1,dis1,e1);
      	disab=dijistra(B,A,head2,dis2,e2);
      	if(disab==INF){printf("-1");return 0;}
      	for(int i=1;i<ent1;i++){
      		int u=e1[i].from,v=e1[i].to,w=e1[i].val;
      		if(dis1[u]+dis2[v]+w==disab) fg[u]=fg[v]=1,ve[i]=1;
      	}
      	discd=dijistra(C,D,head1,dis1,e1);
      	discd=dijistra(D,C,head2,dis2,e2);
      	if(discd==INF){printf("-1");return 0;}
      	for(int i=1;i<ent1;i++){
      		int u=e1[i].from,v=e1[i].to,w=e1[i].val;
      		if(dis1[u]+dis2[v]+w==discd){
      			if(fg[u]||fg[v]) xj=1;
      			if(!ve[i]) continue;
      			add(u,v,w,head3,e3,ent3);
      			in[v]++;			
      		}
      	}
      	topo(C,D,head3,dis3,e3);
      	if(xj) ans++;
      	printf("%lld",ans);
      	return 0;
      }
    • 入门OJ 2083 [Noip模拟题]围篱笆

      和上题一样,也是一道"益智"题

      代码:

      #include<cmath> 
      #include<cstdio>
      #include<cstring>
      #include<iostream>
      using namespace std;
      const double pi=acos(-1);
      int N;
      int main(){
      	while(1){
      		scanf("%d",&N);
      		if(!N) break;
      		printf("%.2lf
      ",1.0*N*N/pi/2);
      	}
      	return 0;
      }
    • 入门OJ 2084 [Noip模拟题]点

      假题,其实选的点可以和原来的点重合。

      代码:

      #include<cstdio>
      #include<cstring>
      #include<iostream>
      #include<algorithm>
      #include<windows.h> 
      #define happy_check(); 
      int RESULT=MessageBox(NULL,TEXT("Are you happy?"),"Just click on it" ,MB_YESNO);if(RESULT==IDNO){
      MessageBox(NULL,TEXT("Poor guy!
      Hope you can be better."),"You are not happy?" ,MB_OK);return 0;}
      using namespace std;
      int x[10005],y[10005];
      int n,lx,ly,cnt,xx,yy,ans;
      int abs(int a){
      	return a<0?-a:a;
      }
      int main(){
      	//happy_check();
      	scanf("%d",&n);
      	for(int i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]);
      	sort(x+1,x+n+1); sort(y+1,y+n+1);
      	if(n&1) cnt=1,xx=x[n/2+1],yy=y[n/2+1]; 
      	else{
      		xx=x[n/2]; lx=x[n/2+1]-x[n/2]+1;
      		yy=y[n/2]; ly=y[n/2+1]-y[n/2]+1;
      		cnt=lx*ly;
      	}
      	for(int i=1;i<=n;i++) ans+=abs(xx-x[i]);
      	for(int i=1;i<=n;i++) ans+=abs(yy-y[i]);
      	printf("%d %d",ans,cnt);
      	return 0;
      }
      
    • 入门OJ 2085 [Noip模拟题]身高

      对于每个约束(a,b)
      那么a,b之间的应该都比a和b小,所以就差分使得该区间整体小一
      注意有重复的(a,b),要去重,否则WA

      (怎么有一个输入的东西没用上?)

      代码:

      #include<cstdio>
      #include<cstring>
      #include<iostream>
      #include<algorithm>
      using namespace std;
      struct cons{
      	int a,b;
      	bool operator <(const cons &rtm) const{
      		return a!=rtm.a?a<rtm.a:b<rtm.b;
      	}
      }t[100005];
      int dif[100005];
      int N,I,H,R;
      int main(){
      	scanf("%d%d%d%d",&N,&I,&H,&R);
      	for(int i=1;i<=R;i++){
      		scanf("%d%d",&t[i].a,&t[i].b);
      		if(t[i].a>t[i].b) swap(t[i].a,t[i].b);
      	}
      	sort(t+1,t+R+1);
      	for(int i=1,j=0;i<=R;i++){
      		if(t[i].a==t[j].a&&t[i].b==t[j].b) continue;
      		dif[t[i].a+1]-=1;
      		dif[t[i].b]+=1;
      		j=i;
      	}
      	for(int i=1;i<=N;i++){
      		H+=dif[i];
      		printf("%d
      ",H);
      	}
      	return 0;
      }
      
    • 入门OJ 2087 [Noip模拟题]lucky

      裸的数位Dp
      输入的数不超过10^20,可能爆long long(包括unsigned long long)
      所以用字符串读入
      (一直wa,最后才发现读入出错了)

      代码:

      #include<cstdio>
      #include<cstring>
      #include<iostream>
      #define ll long long
      using namespace std;
      ll dp[30][12][2];
      ll N,tail,num[30]; 
      ll dfs(int p,int last,bool ach,bool up){
      	if(p>tail) return ach;
      	if(!up&&dp[p][last][ach]!=-1) return dp[p][last][ach];
      	ll ret=0; int r=up?num[p]:9;
      	for(int i=0;i<=r;i++) 
      		ret+=dfs(p+1,i,ach||(last==4&&i==9),up&&i==r);
      	if(!up) return dp[p][last][ach]=ret;
      	return ret;
      }
      int main(){
      	num[++tail]=getchar()-'0';
      	while(num[tail]<0||num[tail]>9) num[tail]=getchar()-'0';
      	while(num[tail]<=9&&num[tail]>=0) num[++tail]=getchar()-'0';
      	tail--;
      	memset(dp,-1,sizeof(dp));
      	cout<<dfs(1,0,0,1);
      	return 0;
      }
      
    • 入门OJ 2088 [Noip模拟题]小球

      模拟,做了超过100000次就停下来

      代码:

      #include<cstdio>
      #include<cstring>
      #include<iostream>
      using namespace std;
      int A,B,cnt; 
      int main(){
      	scanf("%d%d",&A,&B);
      	while(1){
      		if(A>B) swap(A,B);
      		if(!A) break;
      		B-=A;	A+=A;
      		cnt++;
      		if(cnt>100000){
      			printf("-1");
      			return 0;
      		}
      	}
      	printf("%d",cnt);
      	return 0;
      }
    • 晚上
      • BZOJ 1011 [HNOI2008]遥远的行星

        扯题。
            利用题目给的答案误差(大佬博客 ↓)
           
        http://www.cnblogs.com/Sunnie69/p/5575626.html

        代码:

        #include<cstdio>
        #include<cstring>
        #include<iostream>
        #define MAXN 100005 
        using namespace std;
        const double eps=1e-8;
        double m[MAXN],s[MAXN];
        double A,ans;int n,p,B;
        int main(){
            scanf("%d%lf",&n,&A);
            for(int i=1;i<=n;i++) scanf("%lf",&m[i]),s[i]=s[i-1]+m[i];
            p=min(2000,n);
            for(int i=1;i<=p;i++){
                ans=0;
                B=(int)(A*i+eps);
                for(int j=1;j<=B;j++) ans+=m[j]/(1.0*i-j);
                printf("%.6lf
        ",ans*m[i]);
            }
            for(int i=p+1;i<=n;i++){
                B=(int)(A*i+eps);
                ans=m[i]*s[B]/(1.0*i-1.0*B/2);
                printf("%.6lf
        ",ans);
            }
            return 0;
        }
      • BZOJ 1013 [JSOI2008]球形空间产生器sphere

        设出中心的多维坐标
        由给出的n+1个点得出n个等式,
        用高斯消元计算出线性方程的各个元的值
           
        至于高斯消元,自己模拟就好了。

        代码:

        #include<cstdio>
        #include<cstring>
        #include<iostream>
        using namespace std;
        double k[15][15],w[2][15],d[15];
        int n;
        void Gaussian(int p){
        	if(p>n) return;
        	double b,val=0;
        	for(int r=p+1;r<=n;r++){
        		b=k[r][p]/k[p][p];
        		for(int i=p;i<=n+1;i++)
        			k[r][i]=k[r][i]-k[p][i]*b;
        	}
        	Gaussian(p+1);
        	for(int i=p+1;i<=n;i++)
        		val+=d[i]*k[p][i];
        	d[p]=(k[p][n+1]-val)/k[p][p];
        }
        int main(){
        	int cur=0;
        	scanf("%d",&n);
        	for(int i=1;i<=n;i++)scanf("%lf",&w[cur][i]);
        	for(int r=1;r<=n;r++){
        		cur^=1;
        		for(int i=1;i<=n;i++)scanf("%lf",&w[cur][i]);
        		for(int i=1;i<=n;i++){
        			k[r][i]=2*(w[cur^1][i]-w[cur][i]);
        			k[r][n+1]=k[r][n+1]+w[cur^1][i]*w[cur^1][i]-w[cur][i]*w[cur][i];
        		}
        	}
        	Gaussian(1);
        	for(int i=1;i<n;i++)
        		printf("%.3lf ",d[i]);
        	printf("%.3lf",d[n]);
        	return 0;
        }
        
      • BZOJ 1012 [JSOI2008]最大数maxnumber

        可以线段树。
         
        注意到如果向队尾加入一个元素,
        且它前面的元素比它小的话,那么无论怎么询问,它前面的元素都不可能贡献答案
        所以维护一个单调栈,有了单调性后,二分寻找答案。

        代码:

        #include<cstdio>
        #include<cstring>
        #include<iostream>
        #include<algorithm> 
        using namespace std;
        int num[200005],pos[200005];
        int N,D,t,cnt,top,l;
        int main(){
        	scanf("%d%d",&N,&D);
        	char com; int x;
        	for(int i=1;i<=N;i++){
        		scanf(" %c%d",&com,&x);
        		if(com=='A'){
        			++cnt; x=(x+t)%D;
        			while(top&&num[top]<=x) top--;
        			num[++top]=x;
        			pos[top]=cnt;
        		}
        		else if(com=='Q'){
        			x=cnt-x+1;
        			l=lower_bound(pos+1,pos+top+1,x)-pos;
        			t=num[l];
        			printf("%d
        ",t);
        		}
        	}
        	return 0;
        }
        
  • 相关阅读:
    Java——IO输入/输出
    高级查询---嵌套and分页
    Spring mvc拦截器
    SpringMVC实现文件下载
    SpringMVC是实现文件上传
    初始化参数绑定(日期)
    数据校验
    Web Service
    可以用代码发邮件了哦
    JavaMail和James
  • 原文地址:https://www.cnblogs.com/zj75211/p/7646581.html
Copyright © 2011-2022 走看看