NOIP2014模拟8.15

【NOIP2014模拟8.15】城市街区 (Standard IO)
Time Limits: 1000 ms  Memory Limits: 131072 KB     
Description
小A有一个游戏,这个游戏中的某个城市的地图是一个大型方格网,左下角为(-109,-109),右上角为(109,109)。在方格网内部(包括边界)每个整点都是一个路口,每条直线x=x0或y=y0(x0, y0为整数)在方格网内部(包括边界)的部分都是该城市的一条街道。此外,该城市还存在一条斜向的街道,其直线方程为Ax+By+C=0(A, B均不等于0),这条斜向的街道与方格网的交叉点也是路口。现在有N个人,所有人都只能沿着城市的街道行走,其中第i个人要从该城市的路口(ai,bi)走到路口(ci,di)。小A希望计算每个人需要走的最短路径的长度。由于N太大了,小A不想自己算,因此他向你求助。
Input
第一行,四个整数N, A, B, C。
接下来的N行,每行四个整数ai, bi, ci, di。
Output
N行,每行一个实数(保留3位小数),其中第i行的整数表示第i个人需要走的最短路径的长度。
Sample Input
3 2 2 -1
-6 2 2 4
-6 2 -3 -2
-6 2 -8 10
Sample Output
10.000
7.000
8.828
Data Constraint
对于30%的数据,|A|, |B|, |C|, |ai|, |bi|, |ci|, |di|<=10;

对于全部的数据,|A|, |B|, |C|, |ai|, |bi|, |ci|, |di|<=10^9,1<=N<=2000。


这题思路很简单,我的思路是进行5次路径决策,然后取最小值即可。

第一次决策是取曼哈顿距离,接着算出与两个点横纵坐标相同的直线上的点,做另外4次决策取最小值。


虽然这题是水题,但我居然跪了,因为我没注意数据类型,用的是int,结果爆掉了。考试结束后改成long long 就ac了。追悔莫及。值得反思,因为以前也犯过类似错误。这次居然又错不该错的。吸取教训啊。每次打完程序要推敲数据类型使用。



#include
   
   
    
    
#include
    
    
     
     
#include
     
     
      
      
#include
      
      
       
       

using namespace std;

struct node{
	double x,y;
}q[2][2];

long long i,j,k,n,a,b,c;

double dis(double a,double b, double x, double y){
	return sqrt((a-x)*(a-x)+(b-y)*(b-y));
}

double absdl(double a){
	if(a>0)return a;else return -a;
}

double mht(double a,double b,double x,double y){
	return absdl(a-x)+absdl(b-y);
}

int main(){
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	scanf("%lld%lld%lld%lld",&n,&a,&b,&c);

	for(i=1;i<=n;i++){
		long long x[2],y[2];
		scanf("%lld%lld%lld%lld",&x[0],&y[0],&x[1],&y[1]);
		double ans(absdl(x[0]-x[1])+absdl(y[0]-y[1])); 
		q[0][0].x=x[0];
		q[0][0].y=-(a*x[0]+c)/double(b);
		q[0][1].y=y[0];
		q[0][1].x=-(b*y[0]+c)/(double(a));
		q[1][0].x=x[1];
		q[1][0].y=-(a*x[1]+c)/double(b);
		q[1][1].y=y[1];
		q[1][1].x=-(b*y[1]+c)/(double(a));
		for(j=0;j<=1;j++){
			for(k=0;k<=1;k++){
			    ans=min(ans,mht(q[0][j].x,q[0][j].y,x[0],y[0])+mht(q[1][k].x,q[1][k].y,x[1],y[1])+dis(q[1][k].x,q[1][k].y,q[0][j].x,q[0][j].y));		
			}
		}
		if(ans==0)printf("0.000\n");else printf("%.3f\n",ans);
	}
}

      
      
     
     
    
    
   
   


【NOIP2014模拟8.15】因子的排列 (Standard IO)
Time Limits: 1000 ms  Memory Limits: 131072 KB     

Description
一天,小B学习了分解质因数的相关内容。他发现,一个数的质因子可以有许多不同的排列方式,例如20=2*2*5=2*5*2=5*2*2,那么小B认为20的质因子有3种不同的排列方式。小B的同学现在有一个问题:如果一个整数的质因子的不同的排列方式的种类数为k,那么这个整数n(n>1)最小是多少?小B的同学一共有T个不同的k值,希望小B帮助这个同学解决问题。但是小B发现T太大了,并且给出的k值也相当大,因此小B向你求助。
Input

第一行,一个整数T。

接下来的T行,每行一个整数k。

Output

T行,每行一个整数,其中第i行的整数表示第i个k值对应的n的值。

Sample Input
4
1
2
3
105

Sample Output
2
6
12
720

Data Constraint
对于30%的数据,1<n<=100000;
对于全部的数据,1<n<2^63,1<k<2^63,1<=T<=1000。


表示这题考试时不明觉厉。题解很暴力。

对于质因子个数a1,a2,a3,a4

K=(sigmaA)!/(a1!a2!...an!)

然后把所以k对应n跑出来存进有序表里,然后对于询问二分查k输出n

#include
   
   
    
    
#include
    
    
     
     
#include
     
     
      
      
#include
      
      
       
       
#include
       
       
         #include 
        
          const long long ma=LLONG_MAX; using namespace std; struct node{ long long a,b; }f[200010]; long long T,k,tot; int q[65],p[65]; int fac[65]; void factorizate(int a,int b){ int k=a,i=2; while(i<=floor(sqrt(k))) if(!(k%i))k/=i,fac[i]+=b;else i++; fac[k]+=b; } long long calcu(int a,int tot){ memset(fac,0,sizeof(fac)); int i,j,k; for(i=2;i<=a;i++)factorizate(i,1); for(i=1;i<=tot;i++) for(j=2;j<=q[i];j++)factorizate(j,-1); long long w=1,lw=1; for(i=1;i<=63;i++) for(j=1;j<=fac[i];j++){ lw=w; w*=i; if(w 
         
           >1; while(f[mid].a!=k&&l<=r){ if(f[mid].a 
          
            >1; }*/ if(cj<=0)return 0; long long e=calcu(k,dep); if(e>ma||e<0)return 0;else{ // if(f[mid].a!=(long long)e){ f[++tot].a=(long long)(e); f[tot].b=cj; // } } j=1;long long h(0); for(i=1;i<=q[dep];i++){ q[dep+1]=i; j*=p[dep+1]; if(cj>LLONG_MAX/j)break; if(!dfs(dep+1,cj*j,k+i))break; } return 1; } bool cmp(node a,node b){ return ((a.a 
            
            
              >1; while(f[mid].a!=k&&l<=r){ if(f[mid].a 
             
               >1; } while(f[mid-1].a==f[mid].a)mid--; printf("%lld\n",f[mid].b); } } 
              
             
            
           
          
         
       
      
      
     
     
    
    
   
   


【NOIP2014模拟8.15】序列排序 (Standard IO)
Time Limits: 1000 ms  Memory Limits: 131072 KB     

Description

小C有一个N个数的整数序列,这个序列的中的数两两不同。小C每次可以交换序列中的任意两个数,代价为这两个数之和。小C希望将整个序列升序排序,问小C需要的最小代价是多少?

Input

第一行,一个整数N。
第二行,N个整数,表示小C的序列。

Output

一行,一个整数,表示小C需要的最小代价。

Sample Input
6
8 4 5 3 2 7

Sample Output
34
Data Constraint

对于30%的数据,1<=N<=10;
对于全部的数据,1<=N<=100000,输入数据中的其他整数均为正整数且不超过10^9。


这题解题思想值得学习。还是用样例道出解法::

箭头指向数字应在位。可见有很多环。对于每个环的数字归位的最小代价有两种情况::

I  用环中最小数逆着箭头一路换回去Cost=min_circle*(s-2)+sigma_circle{s是环中点数}

II 用数列中最小数辅佐换,最小数先和环内最小数换,在类似I换过去,然后在换回原来位置。

Cost=min_all*(s+1)+sigma+min_circle

最小代价取min即可。

code

#include
   
   
    
    
#include
    
    
     
     
#include
     
     
      
      
#include
      
      
       
       

using namespace std;

struct node{
	int a,b;
}b[100001];

long long i,j,k,n,a[100001],tot(0),d[100001];

bool v[100001];

long long ans;

bool cmp(node a,node b){
	return a.a
       
       
      
      
     
     
    
    
   
   
这道题,我学到了要灵活运用图论知识解决各事物抽象概念关系。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值