Codeforces Round #675 (Div. 2) A - D

    科技2022-08-25  100

    A. Fence

    题意

    为了组成一个四边形,给定三边的长度,求最后一个边的长度

    思路

    我们可以想一下,当一个边固定,其余两个边分别在这个边的两个端点,且边在一边,只有有这个边的角度越大,第三个边越大,当为180°,就会成为一个直线,所以只需要小于三边之和就可以满足不是一个直线的情况,且为最大的可能,必然满足情况

    代码

    #include<iostream> using namespace std; #define int long long signed main(){ int T; cin>>T; while(T--){ int a,b,c; cin>>a>>b>>c; cout<<(a + b + c - 1)<<endl; } return 0; }

    B. Nice Matrix

    题意

    给定一个矩阵,为了使矩阵的行和列都满足回文串的性质,每次操作可以个任意一个数加一或减一,求最小操作数

    思路

    我们可以想象一下回文串的性质,所以一个点要和算他在内的四个点相同(奇数可能为两个个或一个),即求四个点相同的最小步数,和货仓选址是一个道理,只需给他的四份之一的点遍历一遍就可以了

    代码

    #include<iostream> #include<cmath> #include<algorithm> using namespace std; #define int long long const int N = 110; int a[N][N]; signed main(){ int T; cin>>T; while(T--){ int n,m; cin>>n>>m; for(int i = 1;i<=n;i++){ for(int j = 1;j <= m;j++) cin >>a[i][j]; } int ans = 0; for(int i = 1,ii = n;i<=(n + 1)/2;i++,ii--){ for(int j = 1,jj = m;j<=(m + 1)/2;j++,jj--){ int b[4]; b[0] = a[i][j],b[1] = a[i][jj],b[2] = a[ii][j],b[3] = a[ii][jj]; // 对应的4个点 sort(b,b + 4); int x = b[1]; int res = abs(b[0] - b[1]) + abs(b[2] - b[1]) + abs(b[3] - b[1]); // 最小步数使4位相同 if((n & 1)&&i == (n + 1)/2) // 如果两行相同的处理 res /= 2; if((m & 1)&&j == (m + 1)/2) // 列是相同的处理 res /= 2; ans += res; } } cout<<ans<<endl; } return 0; }

    C. Bargain

    题意

    给定一个很大的数,可以从中删除一段连续的部分(非空),这样就能使这个数有很多不同的可能,求这些可能的不同取值

    思路

    我们可以枚举这个数每一位的所有可能的和即在这个数的前面删除,或后面删除。 这个数位 a1a2a3···an-1an 假设他在i位 如果在前面删除 对于从他前面的第一位删除有 i - 1 种 对于从他前面的第两位删除有 i - 2 种 ·········· 对于从他前面的第i - 1位删除有 1 种 即有 i * (i - 1) / 2 中 结果为 ai * 10n-i * i * (i - 1)/2 如果在后面删除, 假设他后面有k为 如果这个数在最后一位,只能把后面的k位都删除,1种可能,且为 ai 如果这个数在倒数第二位,可以把连续的k - 1位删除,2种可能 且为 ai * 10 如果这个数在倒数第三位,可以把连续的k - 2位删除,3种可能 且为 ai * 102 这样我们就能发现所有的规律

    代码

    #include<iostream> #include<cstring> using namespace std; const int N = 1e5+10,mod = 1e9+7; #define int long long char s[N]; int f[N]; signed main(){ scanf("%s",s + 1); int n = strlen(s + 1); int ans = 0,p = 1; int now = 0; // 表示前面的所有可能 for(int i = n;i >= 1;i--){ int v = s[i] - '0'; int cur = (now + (i * (i - 1) / 2) % mod * p % mod)%mod; // 后面加上前面的所有可能 ans = (ans + cur * v) % mod; // 乘上这个数 now = (now + p * (n - i + 1)%mod)%mod; // 对于下一位多了这个数字在后面有n - i + 1位的情况 p = (p * 10) % mod; } cout<<ans<<endl; return 0; }

    感觉有点跳跃性,多看看还是可以理解的

    D. Returning Home

    题意

    给定一个n * n 的地图,给定一个起点和一个终点,求起点到终点需要多少最短时间,走一步时间为1,给了m个神奇的点,如果在x坐标或y坐标在等于神奇的点的x坐标或y坐标,那么就可以瞬移到这个神奇的点

    思路

    我们可以把起点也可以看做神奇的点,因为没有必要走两次起点。我们很容易想到最后走到终点的点必然是这些神奇的点中的一个,一个最暴力的想法就是给这些神奇的点建边,求出到每个点的最短距离,但是这样就要给每个点建立 n - 1 条边即 n * (n - 1) 条边,无论在时间还是空间都是不允许,这就需要我们优化一下边,走到一个点无非是从x方向或y方向,如果在x方向上到达也可以想象成先到比他 x小的最大的那个点或大于x的最小的那个点,在走在这个点,因为他的特性,直接走和这样的时间是等价的,所以我们就可以这样直接建立在x方向上相邻的点和在y方向相邻的点之间的边(只需要建立 4 * n 条边),然后通过dijkstra直接算出到这些点距离。

    代码

    #include<iostream> #include<algorithm> #include<queue> #include<cstring> using namespace std; const int N = 1e5+10,M = 4 * N; #define x first #define y second typedef pair<int ,int > PII; int h[N],e[M],ne[M],w[M],idx; bool st[N]; int d[N],id[N]; PII a[N]; PII ed; bool cmp1(int x,int y){ return a[x].x < a[y].x; } bool cmp2(int x,int y){ return a[x].y < a[y].y; } void add(int a,int b,int c){ e[idx] = b,w[idx] = c,ne[idx] = h[a],h[a] = idx++; } void dijkstra(){ memset(d,0x3f,sizeof d); d[0] = 0; priority_queue<PII ,vector<PII> ,greater<PII>>hp; hp.push({0,0}); while(hp.size()){ auto t = hp.top(); hp.pop(); int ver = t.y,dist = t.x; if(st[ver]) continue; st[ver] = true; for(int i = h[ver];i!=-1;i = ne[i]){ int j = e[i]; if(d[j] > dist + w[i]){ d[j] = dist + w[i]; hp.push({d[j],j}); } } } } int main(){ ios::sync_with_stdio(false); memset(h,-1,sizeof h); int n,m; cin>>n>>m; cin>>a[0].x>>a[0].y; cin>>ed.x>>ed.y; id[0] = 0; for(int i = 1;i <= m;i++){ cin>>a[i].x>>a[i].y; id[i] = i; } sort(id,id + m + 1,cmp1); // x方向排序 for(int i = 1;i<=m;i++){ // x方向建边 int t = a[id[i]].x - a[id[i - 1]].x; add(id[i],id[i - 1],t); add(id[i - 1],id[i],t); } sort(id,id + m + 1,cmp2); // y方向排序 for(int i = 1;i<=m;i++){ // y方向建边 int t = a[id[i]].y - a[id[i - 1]].y; add(id[i],id[i - 1],t); add(id[i - 1],id[i],t); } dijkstra(); int ans = 2e9; for(int i = 0;i<=m;i++){ ans = min(ans,d[i] + abs(ed.x - a[i].x) + abs(ed.y - a[i].y)); // 从神奇的带你到终点 } cout<<ans<<endl; return 0; }
    Processed: 0.022, SQL: 9