• Potato的暑期训练day#3 ——Codeforces Round #549 (Div. 2)


    Potato的暑期训练day#3 ——Codeforces Round #549 (Div. 2)

    题目链接:

    A.http://codeforces.com/problemset/problem/1143/A

    B.http://codeforces.com/problemset/problem/1143/B

    C.http://codeforces.com/problemset/problem/1143/C

    D.http://codeforces.com/problemset/problem/1143/D

    E.http://codeforces.com/problemset/problem/1143/E

    F.http://codeforces.com/problemset/problem/1143/F

    A - The Doors

    水题没什么好说的的

    B - Nirvana

    题意:给出一个n,要求求出小于n中的所有数的各位乘积的最大的是多少

    思路:存下n的每一位,贪心地考虑每一个位置,将这个位置减1,这个位置之前的位保证最大,之后的位置保证全为9,注意特判最大位。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 25;
    int num[maxn];
    int main() {
        int n,cnt = 0;
        scanf("%d",&n);
        while(n) {
            num[cnt++] = n%10;
            n /= 10;
        }
        int sum = 1,ans = -1;
        for(int i = cnt - 1;i>=0;i--) sum *= num[i];
        ans = sum;
        for(int i = cnt - 1;i >= 0;i--) {
            sum = 1;
            for(int j = cnt - 1;j >= 0;j--) {
                if(j>i) {
                    sum *= num[j];
                }
                else if(i == j) {
                    if(j == cnt - 1 && num[j] - 1 == 0) {
                        sum*=1;
                    } 
                    else sum *= (num[j]-1);
                }
                else sum*=9;
            }
            ans = max(sum,ans);
        }
        printf("%d",ans);
        return 0;
    }
    

    C - Queen

    题意:给出一棵树,每个节点有两种状态,1时代表这个节点可能被删除,0表示这个节点不会会删除,当一个节点的所有儿子节点均为1状态时该节点可以删除,删除后他的儿子节点继承其父亲节点

    思路:由于删除节点的所有儿子节点都是1,因此不会有影响,扫一遍即可。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5+5;
    int n;
    int par[maxn],c[maxn],vis[maxn];
    vector<int> G[maxn];
    void del(int s) {
        int x = par[s];
        for(int i = 0;i < G[s].size();i++) {
            par[G[s][i]] = x;
        }
    }
    void solve() {
        int flag = 1;
        for(int i = 1;i <= n;i++) {
            if(c[i]) {
                if(!vis[i]) {
                    del(i);
                    printf("%d ",i);
                    flag = 0;
                }
            }
        }
        if(flag) printf("-1");
    }
    int main() {
        scanf("%d",&n);
        for(int i = 1;i <= n;i++) {
            scanf("%d%d",&par[i],&c[i]);
            if(!c[i]) vis[i] = 1;
            else  {
                G[par[i]].push_back(i);
            }
        }
        for(int i = 1;i <= n;i++) if(c[par[i]] && !c[i]) vis[par[i]] = 1;
        solve();
        return 0;
    }
    

    D - The Beatles

    题意:给出n,k,a,b;表示共有nk个城市,这些城市等距围成一个圆,共有n家餐厅,以1,k+1,2k+1.....均匀地分布在这个圆上,a表示当在起始点s的时候,距离餐厅最近的距离,b表示第一次移动l时距离餐厅最近的距离,已知我们以l的步长移动。

    思路:等价于同余方程 $ l equiv pm apm b modk $ 我们可以解出 (l = kx+l[i]) 其中x为任意整数,l[i]代表ab的正负情况,总的移动步数 = nk/gcd(nk,l[i]+x*k) 我们从0-n-1枚举x就好,这样我们就求出了最大最小

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    ll gcd(ll a,ll b) {
    	return b ? gcd(b,a%b) : a;   
    }
    ll l[4];
    int main() {
    	ll n,k,a,b,now;
    	cin>>n>>k>>a>>b;
    	ll maxans = -1,minans = 1e18;
    	l[0] = (2*k+a+b)%k;
    	l[1] = (2*k+a-b)%k;
    	l[2] = (2*k-a+b)%k;
    	l[3] = (2*k-a-b)%k;
    	for(int i = 0;i < 4;i++) {
    		for(int j = 0;j < n;j++) {
    			now = n*k/gcd(n*k,l[i]+j*k);
    			maxans = max(maxans,now);
    			minans = min(minans,now);
    		}
    	}
    	cout<<minans<<" "<<maxans;
    	return 0;
    }
    

    E - Lynyrd Skynyrd

    题意:给你两个排列a,p,p为1,2,3...n的一个排列,a是长度为m的一个任意排列,现在有q个查询,对于每个[l,r]的查询,表示在排列a 中的[l,r]这个连续序列是否存在子序列是p序列的一个连续段或者能够通过右移得到(也可以把p序列看成一个圆来匹配)

    思路:对于A中的每一个Ai,求出 (Ai在P中的前一个数字)在A中的小于i的最大位置b[i]。比如P是(3,2,1),A是(3,1,2,3),那对于A中的2来说,求出来的b就是1,对于A中第二个3来说,求出来的b就是2,得到的b为(0,0,1,2)。可以通过记录每一个数字最后出现的位置来求每一个Ai的b[i]。
    那对于一个A[i],我们算b[b[b[b[…b[i]]…],套n-1次就可以得到[L,i]这个区间存在以A[i]为结尾的循环右移排列需要的最大的L。直接套的话每一个数字都要算N-1次,是O(n²)的算法,所以我们用倍增的思想,f[i][j]代表第i个数字要得到以它为结尾的长度为2^j的排列所需要的最大的区间左端点L,那么显然f[i][0] = b[i],转移方程为f[i][j+1] = f[ f[i][j] ] [ j ],
    然后用g[i]表示最大的L使得[L,i]这个区间存在P的循环右移,然后利用f[i][j]算一下第i个要到前n-1需要的最大的L,转移方程是g[i] = max(g[i-1],L)。

    对于每个查询[L,R],只要判断L是不是比R大就可以知道[L,R]存不存在P的循环右移了。!

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 2e5 + 50;
    int pre[maxn];
    int n,m,q;
    int p[maxn],a[maxn],pos[maxn];
    int f[maxn][21];
    int g[maxn]; 
    int solve(int x,int num){//利用f[i][j]计算x到前num个数需要的最大左端点
    	for(int i = 20;i >= 0;--i){
    		if((1<<i)&num) x = f[x][i];
    	}
        return x;
    }
    int main(){
    	scanf("%d%d%d",&n,&m,&q);
    	for(int i = 1;i <= n;++i) scanf("%d",&p[i]),pre[p[i]] = p[i-1];
    	pre[p[1]] = p[n];
    	for(int i = 1;i <= m;++i){
    		scanf("%d",&a[i]);
    		pos[a[i]] = i;//记录a[i]这个数字最后一次出现的位置
    		f[i][0] = pos[pre[a[i]]] ;//a[i]的第一个前驱的位置
    		for(int j = 0;j < 20;++j) {
    			f[i][j+1] = f[f[i][j]][j];
    			//a[i]的第2^(j+1)个前驱是a[i]的第2^j个前驱的第2^j个前驱 
    		}
    		g[i] = max(g[i-1],solve(i,n-1));
    	}
    	while(q--){
    		int l,r;scanf("%d%d",&l,&r);
    		if(l<=g[r]) printf("1");
    		else printf("0");
    	}
        return 0;
    } 
    
    

    F - U2 CodeForces - 1143F

    计算几何这种东西就丢给队友了(雾

    我现在最大的问题就是人蠢而且还懒的一批。
  • 相关阅读:
    USBDM RS08/HCS08/HCS12/Coldfire V1,2,3,4/DSC/Kinetis Debugger and Programmer -- Driver Install
    USBDM RS08/HCS08/HCS12/Coldfire V1,2,3,4/DSC/Kinetis Debugger and Programmer -- Software Install
    USBDM Debugger interface for Freescale RS08,HCS08,HCS12,Coldfire and ARM-Kinetis Devices.
    USBDM RS08/HCS08/HCS12/Coldfire V1,2,3,4/DSC/Kinetis Debugger and Programmer -- MC9S08JS16
    USBDM Coldfire V2,3,4/DSC/Kinetis Debugger and Programmer -- MC9S08JS16
    USBDM RS08/HCS08/HCS12/Coldfire V1,2,3,4/DSC/Kinetis Debugger and Programmer -- MC9S08JM16/32/60
    USBDM Kinetis Debugger and Programmer
    What is CMSIS-DAP
    Programming internal SRAM over SWD
    STM32F2x Is it possible to request multiple DMA streams with single request
  • 原文地址:https://www.cnblogs.com/pot-a-to/p/11144143.html
Copyright © 2020-2023  润新知