题解:排序后取中间的数。
题解:检查每一位是否合法就行。
感受:永远都被B题坑.。。。。。if there is a digit kk in the cell, then exactly kk neighboring cells have bombs. 周围只是没炸弹而已,而不是全部'.'。WA了四次,强行掉分,囧rz。
#pragma warning(disable:4996) #include<cmath> #include<string> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define mem(arr,in) memset(arr,in,sizeof(arr)) using namespace std; const int maxn = 1005; int n, m; char mp[200][200]; int dx[] = { -1,-1,0,1,1,1,0,-1 }; int dy[] = { 0,1,1,1,0,-1,-1,-1 }; bool check1(int a, int b) { for (int i = 0; i <= 7; i++) { int mx = dx[i] + a; int my = dy[i] + b; if (mx >= 0 && mx < n && my >= 0 && my < m && mp[mx][my] == '*') return false; } return true; } bool check2(int a, int b) { int cnt = 0; for (int i = 0; i <= 7; i++) { int mx = dx[i] + a; int my = dy[i] + b; if (mx >= 0 && mx < n && my >= 0 && my < m && mp[mx][my] == '*') cnt++; } int k = mp[a][b] - '0'; if (cnt == k) return true; else return false; } bool Solve() { for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (mp[i][j] == '.') { if (!check1(i, j)) return false; } else if (mp[i][j] >= '1' && mp[i][j] <= '8') { if (!check2(i, j)) return false; } } } return true; } int main() { while (cin >> n >> m) { for (int i = 0; i < n; i++) scanf("%s", mp[i]); //for (int i = 0; i < n; i++) printf("%s ", mp[i]); if (Solve()) cout << "YES" << endl; else cout << "NO" << endl; } return 0; }
题解:while(((p*b)%q)) p=p*b%q;这样貌似会超时,比赛的时候不敢写。还有就是判断是否存在k使得,p*b^k/q=0,即q的所有素因子是否在b中存在。
注意:不要用long long!!!
#pragma warning(disable:4996) #include<cmath> #include<string> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define mem(arr,in) memset(arr,in,sizeof(arr)) using namespace std; const int maxn = 1005; int T; ll p, q, b; ll gcd(ll x, ll y) { if (y == 0) return x; return gcd(y, x % y); } int main() { scanf("%d", &T); for (int i = 1; i <= T; i++) { scanf("%I64d %I64d %I64d", &p, &q, &b); if (p == 0) { printf("Finite "); } else { ll d = gcd(p, q); q = q / d; while (1) { d = gcd(b, q); if (d == 1) break; while (q % d == 0) q = q / d; } if (q == 1) { printf("Finite "); } else { printf("Infinite "); } } } return 0; }
题解:f ( l , r ) = f ( l , r - 1 ) ^ f ( l + 1 , r ),则 dp[ l ][ r ]=max(dp[ l ][ r ],dp[ l ][ r - 1 ],dp[ l + 1 ][ r ])。
感受:对位运算不熟啊,异或运算满足结合率和交换率。第一个式子,可以通过 f ( a , b , c , d)归纳出来,证明就不写了,第二个式子意思是,答案就在 f 递归中,要么是 f ( l , r ) , f ( l ,r - 1) , f( l + 1 , r)。如果不预处理出所有区间的最大值,那么就只有在询问中递归寻找最大值,算 f ( l , r )也就没意义了。
#pragma warning(disable:4996) #include<cmath> #include<string> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define mem(arr,in) memset(arr,in,sizeof(arr)) using namespace std; const int maxn = 5005; int n, m; int dp[maxn][maxn]; int main() { while (scanf("%d", &n) != EOF) { for (int i = 1; i <= n; i++) scanf("%d", &dp[i][i]); for (int i = 1; i <= n; i++) { for (int j = i - 1; j >= 1; j--) { dp[j][i] = dp[j][i - 1] ^ dp[j + 1][i]; } } for (int i = 1; i <= n; i++) { for (int j = i - 1; j >= 1; j--) { dp[j][i] = max(dp[j][i], max(dp[j][i - 1], dp[j + 1][i])); } } scanf("%d", &m); for (int i = 1; i <= m; i++) { int l, r; scanf("%d%d", &l, &r); printf("%d ", dp[l][r]); } } return 0; }