键盘侠牧师
你的脸上风淡云轻,谁也不知道你的牙咬得有多紧。你走路带着风,谁也不知道你膝盖上仍有曾摔过的伤的淤青。你笑得没心没肺,没人知道你哭起来只能无声落泪。要让人觉得毫不费力,只能背后极其努力。我们没有改变不了的未来,只有不想改变的过去。

这是2019.11.21日训练的补题

啊哈,我又懒了,该打

 

飞鸽传送

 

A题:

题目的意思呢?给出两个数组,分别表示直线方程y = x + a[i] ,和方程  y = -x = b[i], 问你可不可以算出这两套直线相交的点的坐标是整数的点的数目

思路呢?就是这两套直线呢,相同组的不会相交,不同组才相交,两方程联立 得到 2*x = b[i] - a[i],由此可得b[i]-a[i]的绝对值必须可以整除2

代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;

typedef long long ll;
map<ll,ll>mp;
const int N = 1e5+10;
int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        int n;
        cin >> n;
        int num=0,cunt=0;
        int p =0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&p);
            if(p%2==0)num++;
        }
        int m;
        cin >> m;
        int q = 0;
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&q);
            if(q%2==0)cunt++;
        }
        ll sum = (ll)num * cunt;
        sum += (ll)(n-num)*(m-cunt);
        cout << sum <<endl;
    }
}

B题呢给你n块木板,让你求出一个原点和终点相距最大的路线,每次路线必须转换(只有两个选择,向前向上)

应为距离最大嘛,我们就要尽可能让他的一边最大,就是一个简单的直角三角形啊,我们只需让他的一个直角边尽可能大,他的斜边就越大

代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <string>
 6 #include <algorithm>
 7 
 8 using namespace  std;
 9 typedef long long ll;
10 const int N = 1e5 +10;
11 int a[N];
12 int main()
13 {
14     int n;
15     cin >> n;
16     ll sum =0,s=0,num=0;
17     for(int i =1;i<=n;i++)
18     {
19         scanf("%d",&a[i]);
20         sum+=a[i];
21     }
22     sort(a+1,a+n+1);
23     for(int i=1;i<=n/2;i++)
24     {
25         num+=a[i];
26     }
27     s = (ll)num*num + (sum-num)*(sum-num);
28     cout << s << endl;
29     return 0;
30 }
View Code

 

C题吧,个人觉得挺难得,当时自己都自闭了,觉得是组合数但就是不知道整么求

题意很简单就是一个方格与他有想临边的最多有一个和他颜色相同,只有两种颜色,所以但我们确定了第一行和第一列的颜色分布时就确定了这个图形的颜色分布

确定了第一行,第二行要不和第二行一样,要不就完全相反,确定了第二行也就确定了第三行,这样一次往下影响,因此我们又去确定第一列,第一列就确定了第二行和第一行完全一样还是完全相反,

假设f[i]表示第一行的第几个方格表示白色的方案数 f[i] = f[i-1] + f[i-2]//表示第i个的情况等于第i-1个和第i-2个确定(因为最多有两个连续一样的方格)它的前一个是白色或者前前个是白色,他才可以是白色

f[1] = 1;

f[2]=2;

黑色也一样

因此F[i]表示i个方格的颜色方案F[i] = f[i] * 2;

最后一个 nxm的方格颜色的方案数是  F[n] + F[m] -2, 当第一行第一列颜色不一样时方案无效 只有两个就是黑白间

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <map>

using namespace std;
typedef long long ll;
const int N = 1e5+10;
const ll mod  = 1e9+7;
int f[N];
int main()
{
    int n,m;
    cin >> n >> m;
    f[1]=2;
    f[2]=4;
    for(int i=3;i<=N;i++)
    {
        f[i]=(f[i-1]+f[i-2])%mod;
    }
    cout << (f[n] + f[m] - 2)%mod << endl;
    return 0;
}

D题

题意比较迷茫就是给你一个长度为n的字符串,仅有'(’')'两种字符,将后k个字符换到前面可以组成圈,求最大的圈长度,可以选择一对字符进行交换交换完后再将后k个字符换到前面

这里呢我们可以把‘(’当成1,‘)’当成-1,暴力枚举每一位交换,然后看判断圈的长度

圈的条件‘(’')'必须配对,每一组配对成功长度就加一,有一个不匹配的就不是圈

简单版:

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <cmath>
 5 #include <string>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <map>
 9 
10 using namespace std;
11 
12 typedef long long ll;
13 const int N  = 5e2+10;
14 int a[N];
15 int main()
16 {
17     int n;
18     cin >> n;
19     string s;
20     cin >> s;
21     int ans =0;
22     int x = 0, y = 0;
23     for(int i=0;i<s.size();i++)
24     {
25         for(int j=i+1;j<s.size();j++)
26         {
27             if(s[i]==s[j])continue;
28             swap(s[i],s[j]);
29             int num=0,cun=0,now=0;
30             for(int  k = 0;k<s.size();k++)
31             {
32                 if(s[k]=='(')num++;
33                 else num--;
34                 if(num==now)cun++;
35                 if(num<now) cun =1,now = num;
36             }
37             if(num==0&&cun>ans)ans = cun, x =i ,y =j;
38             swap(s[i],s[j]);
39         }
40     }
41     cout << ans <<endl<< x+1 <<' '<<y+1<<endl;
42     return 0;
43 }
View Code

 

posted on 2019-11-23 17:14  键盘侠牧师  阅读(167)  评论(0编辑  收藏  举报