Codeforces Round #183 (Div. 2) 勾股数 + 时间差+数学
A:
给出a,b,c a<= b<=c <=n 求满足a^2 + b^2 = c^2 的个数。 直接暴力枚举过的。。
来个优化的
假设直角三角形三边为a,b,c; 则a = 2*m*n, b = m*m - n*n, c =m*m + n*n;
这样我们只要枚举m,然后再枚举n, 就好了
int gcd(int a,int b) { if(a%b == 0) return b; a = a%b; return gcd(b,a); } int main() { int n; cin>>n; int top = sqrt(1.0*n); int ans = 0; for (int i = 1; i <= top; ++i) { for (int j = 1; j < i && (i*i + j*j <= n); ++j) { if ((i - j)%2 == 1 && gcd(i,j) == 1) ans += n/(i*i + j*j); } } cout<<ans; return 0; }
B:
给出两个时间yyyy:mm:dd 所这两个时间之间的天数,这样的题目,一天一天的算比较好,不用考虑很多情况。
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll long long #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define M 30007 #define N 2007 using namespace std; const int inf = 100000007; const int mod = 1000000007; const double eps = 1e-6; bool isL(int y) { if ((y%4 == 0 && y%100 != 0) || y%400 == 0) return true; else return false; } int getR(int y,int m) { if (m == 1 || m == 3 || m == 5 || m == 7 || m == 8 || m == 10 || m == 12) return 31; if (m == 2) { if (isL(y)) return 29; else return 28; } return 30; } void next(int &y,int &m,int &d) { d++; int day = getR(y,m); if (d > day) d -= day,m++; if (m > 12) m -= 12,y++; } int main() { int y1,m1,d1; int y2,m2,d2; int ans = 0; scanf("%d:%d:%d",&y1,&m1,&d1); scanf("%d:%d:%d",&y2,&m2,&d2); if (y1 > y2) { swap(y1,y2); swap(m1,m2); swap(d1,d2); } else if (y1 == y2 && m1 > m2) { swap(y1,y2); swap(m1,m2); swap(d1,d2); } else if (y1 == y2 && m1 == m2 && d1 > d2) { swap(y1,y2); swap(m1,m2); swap(d1,d2); } while (y1 != y2 || m1 != m2 || d1 != d2) { ans++; next(y1,m1,d1); } printf("%d\n",ans); return 0; }
C:
给出一个数n,求三个这n个数的排列a[],b[],c[],使得 (a[i] + b[i])%n = c[i]%n ..
我们可以发现只要:当n是奇数的时候使a[i] = b[i]然后a[i] + b[i] 随着i的增加是不断+2的。也就是0,2,4....然后模上奇数的话,肯定会出现1,然后再不断+2然后肯定能把0 - n -1 都求出来,至此,奇数的就可以处理了。
当n为偶数时,a[i] + b[i]不断的+2 会出现0 ,2,4.....0的情况,然后暴力一下小数据,发现应该是然后就可以做了。
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll long long #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define M 30007 #define N 2007 using namespace std; const int inf = 100000007; const int mod = 1000000007; const double eps = 1e-6; int main() { int n; int i; scanf("%d",&n); if (n%2 == 0) printf("-1\n"); else { for (i = 0; i < n; ++i) printf("%d ",i); printf("\n"); for (i = 0; i < n; ++i) printf("%d ",i); printf("\n"); for (i = 0; i < n; ++i) printf("%d ",(i + i)%n); printf("\n"); } return 0; }
D:
题意:
给你一个n*m的矩形,然后给定矩形内的一个点(x,y)。求该矩形的子矩形,是的该子矩形的面积最大,如果存在多个面积相同的使的该子矩形的中心距离(x,y)最近,如果还存在多个那么要求(x1,y1,x2,y2)的字典序最小。
思路:
首先我们能够根据b/a 来确定最大的子矩形的长与宽,然后在判断该矩形应该怎么放,首先检查x方向,看能否将x作为中心,如果不能,然后就是左右移动是的距离小的距离最小,并且x1,x2的字典序是最小的,同样的方法检查y,即可。
这个由于n,m比较大。所以枚举其中一个的话,会超时。只要求出n/a m/b的最小值,就能确定长宽了。
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll long long #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din", "r", stdin) #define Write() freopen("dout", "w", stdout) #define M 137 #define N 5004 using namespace std; const int inf = 0x7f7f7f7f; const int mod = 1000000007; int gcd(int x,int y) { if (y == 0) return x; else return gcd(y,x%y); } int main() { // Read(); int n,m,x,y; ll a,b; cin>>n>>m>>x>>y>>a>>b; int tmp = gcd(a,b); a /= tmp; b /= tmp; ll tx,ty; int k = min(n/a,m/b); tx = k*a; ty = k*b; int x1 = 0,y1 = 0,x2 = 0,y2 = 0; if (x - (tx + 1)/2 >= 0 && x + tx/2 <= n) { x1 = x - (tx + 1)/2; x2 = x + tx/2; // printf(">>>%d\n",x2); } else { if (x - (tx + 1)/2 < 0) { x1 = 0; x2 = x + (tx - x); // printf("**>>>%d %d\n",tx,x2); } else if (n < x + tx/2) { x2 = n; x1 = n - tx; } } /* sdfsf */ if (y - (ty + 1)/2 >= 0 && m >= y + ty/2) { y1 = y - (ty + 1)/2; y2 = y + ty/2; } else { if (y - (ty + 1)/2 < 0) { y1 = 0; y2 = y + ty -y; } else if (m < y + ty/2) { y2 = m; y1 = m - ty; } } printf("%d %d %d %d\n",x1,y1,x2,y2); return 0; }
E:
题意:
给定n个数,然后让你随意的拿走至多k个数,使得剩余数中任意两个数a[i]%m != a[j]%m求最小的 m
思路:
我们首先求出任意两个数的差值,然后记录差值为x的个数,只要存在差值能被m整除那么这两个数肯定不能存在剩余数中,然后我们用O(10^6)枚举m,然后检查余数相同的个数,与k比较。这样的话时间复杂度很好O(n*10^6) .然后看到一个剪纸,就是我们最多能够允许的出现差值相同的对数为k*(k + 1)/2; 只要大于这个数,我们直接忽略即可。
在n个数中所允许出现最多的情况是 1,2,3,4 a[2] - a[1]=m, a[3] - a[1] = 2*m.... 这样允许出现的对数是最多的并且为k*(k + 1)/2;
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll __int64 #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din", "r", stdin) #define Write() freopen("dout", "w", stdout) #define M 137 #define N 5004 using namespace std; const int inf = 0x7f7f7f7f; const int mod = 1000000007; int a[N],b[N*200]; bool vt[N*200]; int main() { // Read(); int i,j; int n,k; scanf("%d%d",&n,&k); for (i = 1; i <= n; ++i) scanf("%d",&a[i]); sort(a + 1,a + 1 + n); CL(b,0); for (i = 2; i <= n; ++i) { for (j = 1; j < i; ++j) { b[a[i] - a[j]]++; } } // printf("<<>>%d\n",n - k); for (i = n - k; i <= 1000001; ++i) { int cnt = 0; for (j = i; j <= a[n]; j += i) cnt += b[j]; if (cnt > k*(k + 1)/2) continue; CL(vt,false); cnt = 0; for (j = 1; j <= n; ++j) { int p = a[j]%i; if (!vt[p]) vt[p] = true; else cnt++; } // printf(">>%d",cnt); if (cnt <= k) break; } printf("%d\n",i); return 0; }