zoukankan      html  css  js  c++  java
  • 19级暑假第七场训练赛

    A: CodeForces - 1300A

    Input

    1
    1
    1
    

    Output

    0
    

    思路:

    循环遍历输入,如果读入0,cnt++,sum++,如果这样sum == 0,cnt++即可

    写的时候莫名写错,搞得WA2发

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int n;
    void solve() {
    	cin >> n;
    	int sum = 0;
    	int cnt = 0;
    	int tt;
    	for (int i = 1; i <= n; i++)
    	{
    		cin >> tt;
    		if (tt == 0)
    			cnt++, tt++;
    		sum += tt;
    	}
    	if (sum == 0) cnt++;
    	cout << cnt << endl;
    }
    
    int main() {
    	//freopen("in.txt", "r", stdin);
    	int t; cin >> t;
    	while (t--)solve();
    }
    

    B:ZOJ - 4107

    题意:

    给定一个序列,让你消除某个数,所得序列最高峰最少是多少

    思路:

    没做出来,解法摘自网络

    例如样例 1 1 4 5 1 4 无论如何消除一个数,最后结果都是1,

    但是样例 1 9 1 9 8 1 0 只要把第三个数 1 消除,得到1 9 9 8 1 0,就没有最高峰了答案为0。

    实际上直接暴力就行了,首先求出原本有多少个峰,然后每次模拟消除一个数,看最多能消除多少个,最后拿原本的减去消除最多的就可以了

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int inf = 99999999999;
    const int maxn = 1e5 + 100;
    ll a[maxn];
    void solve() {
    	int n; cin >> n;
    	a[0] = a[n + 1] = inf;
    	for (int i = 1; i <= n; ++i)cin >> a[i];
    	ll sum = 0;//sum代表原序列中有多少个峰
    	for (int i = 2; i <= n - 1; i++)
    		if (a[i - 1] < a[i] && a[i + 1] < a[i])
    			sum++;
    	ll ansans = 0;
    	for (int i = 1; i <= n - 1; i++) {
    		ll ans = 0, ans1 = 0;
    		if (a[i - 1] > a[i + 1] && a[i - 1] > a[i - 2])//ans代表消除之后 
    			ans++;
    		if (a[i + 1] > a[i - 1] && a[i + 1] > a[i + 2])
    			ans++;
    		if (a[i - 1] > a[i - 2] && a[i - 1] > a[i])//ans1代表消除之前 
    			ans1++;
    		if (a[i + 1] > a[i + 2] && a[i + 1] > a[i])
    			ans1++;
    		if (a[i] > a[i - 1] && a[i] > a[i + 1])
    			ans1++;
    		ansans = max(ansans, ans1 - ans);//做差取最大 
    	}
    	cout << sum - ansans << endl;
    }
    
    int main() {
    	//freopen("in.txt", "r", stdin);
    	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    	int t; cin >> t;
    	while (t--)solve();
    }
    

    C:ZOJ - 4108

    Sample Input

    6
    1 2
    1 3
    1 4
    1 5
    123456 12345678987654321
    123 20190427201904272019042720190427
    

    Sample Output

    0
    0
    1
    0
    0
    1
    

    注释:这道题有规律,前12项如下(1代表奇数,0代表偶数)

    下标n 0 1 2 3 4 5 6 7 8 9 10 11
    Fn 1 1 2 3 5 8 13 21 34 55 89 144
    Sn 1 2 4 7 12 20 33 54 88 143 232 376
    Sn奇偶性 1 0 0 1 0 0 1 0 0 1 0 0

    由图中可以看出前n项斐波纳契数的和呈“1 0 0”的规律,3个一循环。

    a,b的位数高达10000位,所以用char乐行输入,然后转化为整型。

    有一个小知识:对于一个数,它的各个位数之和能够被3整除,那么这个数就是3的倍数。

    让下标从0开始很巧妙,即能被3整除的下标对应的Sn是奇数,剩下的都是偶数。即各个位数之和对3取余为0则是“ 1 0 0”的第一个数1,取余为1是是“1 0 0”的中的第二个数0,取余为2是“1 0 0”中的第三个数0。

    题目要求第a个和第b个之间斐波纳契数之和是奇数还是偶数,即求前b项和-前(a-1)项的和的奇偶性。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    char a[10010], b[10010];
    int c[3] = { 1,0,0 };
    
    void solve() {
        memset(a, 0, sizeof(a));
        memset(b, 0, sizeof(b));
        scanf("%s", a);
        scanf("%s", b);
        int aa = strlen(a);
        int bb = strlen(b);
        int sa = 0, sb = 0;
        for (int i = 0; i < aa; i++) {
            sa += a[i] - '0';
        }
        for (int i = 0; i < bb; i++) {
            sb += b[i] - '0';
        }
        sa = sa - 2;//前a-1项和的奇偶
        sb = sb - 1;//前b-1项和的奇偶
        if (sa == -1) {
            if (c[sb % 3] % 2 == 0)
                printf("0
    ");
            else
                printf("1
    ");
        }
        else {
            if (c[sa % 3] == c[sb % 3])
                printf("0
    ");
            else
                printf("1
    ");
        }
    }
    
    int main() {
    	//freopen("in.txt", "r", stdin);
    	//ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);//得注释掉,影响字符串读入
    	int t; cin >> t;
    	while (t--)solve();
    }
    

    D:CodeForces - 987C

    样例输入1

    5
    2 4 5 4 10
    40 30 20 10 40
    

    样例输出1

    90
    

    样例输入2

    3
    100 101 100
    2 4 5
    

    样例输出2

    -1
    

    样例输入3

    10
    1 2 3 4 5 6 7 8 9 10
    10 13 11 14 15 12 13 13 18 13
    

    样例输出3

    33
    

    题目:要求$$i < j < k, a[ i ] < a[ j ] <a[ k ]; b[ i ] + b[ j ] + b[ k ]$$的最小值;

    先求两个的和,再反向推出三个的和。。。算是用了两遍 (dp) 吧。。。

    #include<bits/stdc++.h>
    #define ms(a,b) memset(a,b,sizeof a)
    using namespace std;
    typedef long long ll;
    const int maxn = 3e3 + 10;
    const int inf = 0x3f3f3f3f;
    ll a[maxn], b[maxn], val[maxn];
    int n;
    bool book[maxn];
    
    void solve() {
    	ms(book, false); cin >> n;
    	for (int i = 1; i <= n; ++i)cin >> a[i];
    	for (int i = 1; i <= n; ++i)cin >> b[i];
    	for (int i = 1; i <= n; ++i) {
    		ll m = inf;
    		val[i] = b[i];
    		for (int j = i - 1; j > 0; --j)
    			if (a[i] > a[j])
    				m = min(m, b[j]);
    		if (m != inf)
    			book[i] = true, val[i] += m;
    	}
    	ll ans = 1 << 30;
    	for (int j = 1; j <= n; j++) {
    		if (!book[j]) continue;
    		for (int k = j + 1; k <= n; k++)
    			if (a[j] < a[k]) 
    				ans = min(ans, val[j] + b[k]);
    	}
    	if (ans == (1 << 30))cout << -1 << endl;
    	else cout << ans << endl;
    }
    
    int main() {
    	//freopen("in.txt", "r", stdin);
    	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    	solve();
    }
    

    E:ZOJ - 4104

    题意:给定一个序列,每次可以把一个元素移到列首(最左边),求最少移几次使其有序(非降序)

    (之前做过类似的题,可以把元素移到首或尾,思路相似)

    思路:因为左移,可以肯定移动的都是较小值,若要保证操作次数最少,最大值一定不需要移动。

    所以先排好序,确定之间的相对大小,然后找到最大值位置(因为有相同元素so从右往左找)

    再从最大值往左找次大值,因为除最大值外,次大值就是当前最大值,所以同样不需要移动。

    以此类推,直到找到最左边结束,我们找到的值都是不需要移动的,那么用总个数n减不需移动的个数 (ans) 即为需要移动的个数,解保证最小。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    int a[100005],b[100005];
    
    int main(){
        int t,n,i,j;
        scanf("%d",&t);
        while(t--){
            scanf("%d",&n);
            int ma=0;
            for(i=1;i<=n;i++){
                scanf("%d",&a[i]);
                b[i]=a[i];
            }
            sort(b+1,b+n+1);
            int ans=0;
            for(i=n;i>=1;i--){
                if(a[i]==b[n]){
                    int c=n;
                    for(j=i;j>=1;j--){
                        if(a[j]==b[c]){
                            c--;
                            ans++;
                        }
                    }
                    break;
                }
            }
            printf("%d
    ",n-ans);
        }
        return 0;
    }
    

    F:CodeForces - 1365D

    采用的是记忆化搜索,唯一的技巧就是隔断的设置

    [if(mp[nr][nc]=='B'){vis[r][c]=-1;return;} ]

    #include <stdio.h>
    int n,m,vis[55][55],k[][2]={{-1,0},{1,0},{0,-1},{0,1}};//UP,DOWN,LEFT,RIGHT
    char mp[55][55];
    void dfs(int r,int c){
    	int nr,nc,i;
    	if(vis[r][c]!=0)return;
    	if(mp[r][c]=='#'||mp[r][c]=='B'){vis[r][c]=-1;return;}//遇到墙,遇到坏蛋
    	for(i=0;i<4;i++){
    		nr=r+k[i][0],nc=c+k[i][1];
    		if(1<=nr&&nr<=n&&1<=nc&&nc<=m)
    			if(mp[nr][nc]=='B'){vis[r][c]=-1;return;}//找坏蛋,设置墙,A cell that initially contains 'G' or 'B' cannot be blocked and can be travelled through.虽然有此句的限制,但是还是可以设置vis[r][c]=-1
    	}
    	vis[r][c]=1;//mp[r][c]=='G','.'
    	for(i=0;i<4;i++){
    		nr=r+k[i][0],nc=c+k[i][1];
    		if(1<=nr&&nr<=n&&1<=nc&&nc<=m)
    			if(!vis[nr][nc])dfs(nr,nc);//mp[nr][nc]=='G','.','#'
    	}
    }
    void solve(){
    	int i,j,flag=0;
    	scanf("%d%d",&n,&m);
    	for(i=1;i<=n;i++)
    		for(j=1;j<=m;j++)
    			vis[i][j]=0;
    	for(i=1;i<=n;i++)scanf("%s",mp[i]+1);
    	dfs(n,m);
    	for(i=1;i<=n;i++){
    		for(j=1;j<=m;j++)
    			if(mp[i][j]=='G'&&vis[i][j]!=1){flag=1;break;}//vis[i][j]==1,'G'没有被访问到;vis[i][j]==-1,或者为了挡住'B',不得不挡住'G'
    		if(flag)break;
    	}
    	if(flag)printf("No
    ");
    	else printf("Yes
    ");
    }
    int main(){
    	int t;
    	scanf("%d",&t);
    	while(t--)solve();
    	return 0;
    }
    

    G:CodeForces - 1352C

    Input:
    6
    3 7
    4 12
    2 1000000000
    7 97
    1000000000 1000000000
    2 1
    Output:
    10
    15
    1999999999
    113
    1000000001
    1
     
    3 7
    (1,2,3,不能被3整除的数1,2),(4,5,6,不能被3整除的数4,5),
    (7,8,9,不能被3整除的数7,8),(10,11,12,不能被3整除的数10,11)
    周期是3,每个周期内不能被3整除的数有2个.故第7个数这样算7/2=3,3*3=9,9+7%2=9+1=10
    输出10
     
    4 12
    (1,2,3,4,不能被4整除的数1,2,3),(5,6,7,8,不能被4整除的数5,6,7),
    (9,10,11,12,不能被4整除的数9,10,11),(13,14,15,16不能被4整除的数13,14,15)
    周期是4,每个周期内不能被4整除的数有3个.故第12个数这样算12/3=4,4*4=16,16-1=15
    输出15
    

    AC代码如下

    #include <stdio.h>
    #define LL long long
    int main(){
    	int t;
    	LL n,k,c,ans;
    	scanf("%d",&t);
    	while(t--){
    		scanf("%lld%lld",&n,&k);
    		c=n-1;//每n个数里,不能被n整除的数有n-1个
    		if(k%c==0)ans=n*(k/c)-1;
    		else ans=n*(k/c)+k%c;
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    

    The desire of his soul is the prophecy of his fate
    你灵魂的欲望,是你命运的先知。

  • 相关阅读:
    zombie处理
    exec
    fork
    udp program
    PS中进程状态
    关闭socket连接最好的方法
    setsockopt
    【Python】Webpy 源码学习
    web.py 安装
    WSGI、flup、fastcgi、web.py的关系
  • 原文地址:https://www.cnblogs.com/RioTian/p/13543168.html
Copyright © 2011-2022 走看看