这是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 }
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 }