• [ABC191] AtCoder Beginner Contest 191


    AtCoder Beginner Contest 191

    Tasks


    Task Name Time Limit Memory Limit
    A Vanishing Pitch 2 sec 1024 MB Submit
    B Remove It 2 sec 1024 MB Submit
    C Digital Graffiti 2 sec 1024 MB Submit
    D Circle Lattice Points 2 sec 1024 MB Submit
    E Come Back Quickly 3 sec 1024 MB Submit
    F GCD or MIN 2 sec 1024 MB Submit

    A Vanishing Pitch

    小学数学题。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    
    int main()
    {
    //	freopen("1.in","r",stdin);
    	int v,t,s,d;
    	cin>>v>>t>>s>>d;
    	if(d<t*v || d>s*v) puts("Yes");
    	else puts("No");
    	return 0;
    }
    

    B Remove It

    签到题。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    
    int n,m;
    
    int main()
    {
    //	freopen("1.in","r",stdin);
    	int x;
    	
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++) {
    		scanf("%d",&x);
    		if(x!=m) printf("%d ",x);
    	}
    	puts("");
    	return 0;
    }
    

    C Digital Graffiti

    题意:给定一个网格图上的多边形,求这个多边形有多少条边。

    Sample Input 1

    5 5
    .....
    .###.
    .###.
    .###.
    .....
    

    Sample Output 1

    4
    

    模拟题。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    
    const int N=200+5;
    const int dx[]={0,0,1,-1},dy[]={1,-1,0,0};
    
    int n,m;
    char a[N][N];
    bool st[N][N][4]; 
    
    int main()
    {
    //	freopen("1.in","r",stdin);
    	int i,j,k;
    	int x,y;
    	
    	scanf("%d%d",&n,&m);
    	for(i=1;i<=n;i++) 
    		scanf("%s",a[i]+1);
    	
    	int ans=0;
    	for(i=2;i<n;i++) 
    		for(j=2;j<m;j++) {
    			for(k=0;k<4;k++) {
    				if(a[i][j]=='.') continue;
    				
    				x=i+dx[k]; y=j+dy[k];
    				if(a[x][y]!='.') continue;
    				if(k<2) st[i][j][k]=st[i-1][j][k];
    				else if(k>=2) st[i][j][k]=st[i][j-1][k];
    				
    				if(!st[i][j][k])
    					ans++,st[i][j][k]=true;//,printf("%d %d %d
    ",i,j,k);
    			}	
    		}
    	
    	cout<<ans<<endl;
    	return 0;
    }
    

    D Circle Lattice Points

    题意:给定一个圆,求圆内或圆上的整点数量。(0<R≤10^5)

    全场最毒瘤的一道题,卡精度差评。

    思路:肯定是枚举一维,(mathcal O(1)) 计算另一维。

    然而交上去 WA 了无数次,心态爆炸。

    WA 的原因大概是有一个点恰恰好好在圆上,然后 long double= 又不准。

    卡精度方法

    • long double
    • 先把 半径 (r) 加上一个很小的值,这样就不会有点在圆上,计算圆内的点就可以了。

    貌似 cmath 里的 floorceil 精度还挺高的,就不用换了。

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    
    #define double long double
    const double eps=1e-14;
    
    double a,b,r;
    
    int main()
    {
    //	freopen("1.in","r",stdin);
    
    	cin>>a>>b>>r;
    	
    	LL ans=0;
    	r+=eps;
    	for(int x=a-r-1;x<=a+r+1;x++) {
    		if(r*r<(x-a)*(x-a)) continue; 
    		double yu=sqrt(r*r-(x-a)*(x-a))+b;
    		double yd=-sqrt(r*r-(x-a)*(x-a))+b;
    	
    		ans+=floor(yu)-ceil(yd)+1;
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    

    E Come Back Quickly

    题意:求每个点所在的最小环。

    (0 le n,m le 2000)

    经典问题:求最短路时,先用 (x) 松弛一遍与 (x) 相邻的点,但不把 (x) 入队,把与 (x) 相邻的点入队。然后到 (x) 的最短路就是答案。

    自证不难

    Code:

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    
    const int N=2e3+5,INF=0x3f3f3f3f;
    
    int one[N],idx;
    int ver[N],edge[N],Next[N];
    inline void AddEdge(int a,int b,int c)
    {
    	Next[idx]=one[a]; ver[idx]=b; edge[idx]=c; one[a]=idx++;
    }
    
    int dis[N];
    bool vis[N];
    
    void spfa(int st)
    {
    	memset(dis,0x3f,sizeof dis);
    	memset(vis,0,sizeof vis);
    	queue<int> q;
    	
    	int i;
    	int x,y,z;
    	
    	for(i=one[st];~i;i=Next[i]) {
    		y=ver[i]; z=edge[i];
    		if(dis[y]>z) {
    			dis[y]=z;
    			if(!vis[y]) 
    				q.push(y),vis[y]=true;
    		}
    	}
    	
    	while(q.size()) {
    		x=q.front(); q.pop();
    		vis[x]=false;
    		for(i=one[x];~i;i=Next[i]) {
    			y=ver[i]; z=edge[i];
    			if(dis[y]>dis[x]+z) {
    				dis[y]=dis[x]+z;
    				if(!vis[y]) 
    					q.push(y),vis[y]=true;
    			}
    		} 
    	}
    }
    
    int n,m;
    
    int main()
    {
    //	freopen("1.in","r",stdin);
    	int i;
    	int x,y,z;
    	
    	scanf("%d%d",&n,&m);
    	memset(one,-1,sizeof one);
    	for(i=1;i<=m;i++) {
    		scanf("%d%d%d",&x,&y,&z);
    		AddEdge(x,y,z);
    	}
    	for(i=1;i<=n;i++) {
    		spfa(i);
    		if(dis[i]==INF) puts("-1");
    		else printf("%d
    ",dis[i]); 
    	}
    	return 0;
    }
    

    F GCD or MIN

    非常有趣的一道思维题。

    Problem Statement

    There are N integers A1,A2,A3,…,AN written on a blackboard.
    You will do the following operation N−1 times:

    • Choose two numbers written on the blackboard and erase them. Let (x) and (y) be the erased numbers. Then, write (gcd(x,y)) or (min(x,y)) on the blackboard.

    After N−1 operations, just one integer will remain on the blackboard. How many possible values of this number are there?

    Constraints

    • (2≤N≤2000)
    • (1≤Ai≤10^9)
    • All values in input are integers.

    思路:

    简化模型。

    原问题A:

    • (x,y o min(x,y))
    • (x,y o gcd(x,y))

    考虑画出决策树,我们发现 (min(x,y)) 操作相当于把较小的数删除。

    有 B:

    • (x,y o delete : y,xle y)
    • (x,y o gcd(x,y))

    想要删除 (y) ,用 (x) 删和用 (a_{min}) 删是一样了,不妨规定都用 (a_{min}) 删(简化了)。

    有 C:

    • (y o delete : y, y ge a_{min})
    • (x,y o gcd(x,y))

    现在的操作流程:取一些数的 (gcd) ,用数列中最小的数删数,取一些数的 (gcd) ,用数列中最小的数删数,取一些数的 (gcd) ,用数列中最小的数删数,(cdots)

    考虑 (a_{min}) 的取值,可能是原来的 (a_{min}) 也可能是新生成的 (gcd) .

    因为 (gcd(x,y)le min(x,y)) ,所以数列中的数如果现在删 删的掉,以后删也都删得掉 。

    不妨都留在后面删。

    有一个考虑的细节:删数时删掉 生成的 (gcd) 和删掉 原序列里生成 该 (gcd)(a_i) 们是等价的,因此我们可以只删除原序列的数。

    现在的操作流程:取一些数的 (gcd) ,用数列中最小的数删数,删光,只剩下之前生成的一个 (gcd)

    删光的条件:(设 (a'_{min}) 为原序列的最小值)

    • 倘若 (a'_{min}) 在序列中,只需 (gcd le a'_{min})
    • 倘若 (a'_{min})(gcd) 中,那么已经有 (gcd le a'_{min})

    故只需 (gcd le a'_{min})

    故原问题转化为

    [sum_{S in A} [gcd(S) le a'_{min}] ]

    由于 (gcd) 一定是某个 (a_i) 的约数。

    故最多有 (nsqrt{A_{max}}) 个。

    一个一个拿出来 check 即可。

    check(d) :判断能不能生成 (d)

    • 对于 不是 (d) 的倍数的 (a_i) ,肯定不能放进来。
    • 对于 (d|a_i) ,放进 (a_i) 只会使 答案变小,不会变大。

    因此把 (d|a_i)(a_i) 求一遍 (gcd) ,看看是否满足即可。

    实现时还有一点技巧。

    Code:

    #include<map>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    
    int gcd(int a,int b)
    {
    	if(b==0) return a;
    	else return gcd(b,a%b);
    }
    
    const int N=2048;
    
    map<int,int> mp;
    int n;
    int a[N];
    
    int main()
    {
    //	freopen("1.in","r",stdin);
    	int i,j;
    	
    	scanf("%d",&n);
    	for(i=1;i<=n;i++) 
    		scanf("%d",&a[i]);
    	sort(a+1,a+n+1);
    	for(i=1;i<=n;i++) {
    		for(j=1;j*j<=a[i];j++) {
    			if(a[i]%j==0) {
    				if(j<=a[1]) mp[j]=gcd(mp[j],a[i]);
    				if(a[i]/j<=a[1]) mp[a[i]/j]=gcd(mp[a[i]/j],a[i]); 
    			}
    		}
    	}
    	int ans=0;
    	for(map<int,int>::iterator it=mp.begin();it!=mp.end();it++) 
    		if(it->first==it->second) ans++;
    	printf("%d
    ",ans);
    	return 0;
    }
    

    参考文章

  • 相关阅读:
    Html 表单表格 form table
    JavaWeb -- 服务器传递给Servlet的对象 -- ServletConfig, ServletContext,Request, Response
    JavaWeb -- Servlet运行过程 和 细节
    调用DLL中的过程和函数
    调用DLL中的过程和函数
    动态载入 DLL
    动态载入 DLL
    静态载入 DLL
    DLL的加载和调用
    静态载入 DLL
  • 原文地址:https://www.cnblogs.com/cjl-world/p/14477293.html
Copyright © 2020-2023  润新知