A. Table
题意:水题
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int main(){ int n , m , x; int ans = 4; scanf("%d%d" , &n , &m); for(int i = 0 ; i < n ; i++){ for(int j = 0 ; j < m ; j++){ scanf("%d" , &x); if(x && (i == 0 || i == n-1 || j == 0 || j == m-1)) ans = 2; } } printf("%d\n" , ans); return 0;
B. Permutation
题意:给定n个k,要求找到一个序列长度为2*n并且序列每个数1~2n区间的某个值。这个序列要满足.
思路:对上面的等式进行化简可以得到|a1-a2| + |a3-a4| + ... + |a2i-1-a2i| - | (a1-a2) + (a3-a4) + ... + (a2i-1-a2i)| = 2K , 并且题目规定2k <= n 。
由于这个序列的每个数是1~2n的某个值,那么如果让这个序列为1,2,3,4....2n-1,2n,那么等式的值为n-n = 0。通过观察等式我们可以知道|a1-a2| + |a3-a4| + ... + |a2i-1-a2i|这个式子的值和a1,a2,a3,a4的顺序无关,那么我们只要让| (a1-a2) + (a3-a4) + ... + (a2i-1-a2i)|这个式子的值为2k-n即可,其实就是变换k对的a的顺序。
代码:
// this is Problem B #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int MAXN = 50010; int main(){ int n , k; scanf("%d%d" , &n , &k); int ans[2*MAXN]; for(int i = 1 ; i <= n*2 ; i += 2){ ans[i] = i; ans[i+1] = i+1; } int j = 1; for(int i = 1 ; i <= k ; i++ , j+=2) swap(ans[j] , ans[j+1]); for(int i = 1 ; i < 2*n ; i++) printf("%d " , ans[i]); printf("%d\n" , ans[2*n]); return 0; }
C Prime Number
题意:给定n个数和x,令 = t/s,求t和s的最大公约数
思路:我们可以把左边的式子进行化简,得到x^(sum-a1)+x^(sum-a2)+...+x^(sum-an) / x^sum
由于分子和分母都是和x有关的等式,我们假设分子中的最小项为min,那么可以化简为
x^(sum-a1)+x^(sum-a2)+...+x^(sum-an) / x^sum = min*a / b
因为min是最小的,因此a和b的最小公约数为1,因此答案就是min,所以我们要求的就是min
但是要注意的是假设分子中有多项的min,比如min = 2^2,但是现在有5项,即5*2^2,我们应该要进行升幂运算
代码:
#include<map> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long int64; const int MOD = 1e9+7; const int MAXN = 100010; int n , x; int num[MAXN]; int64 sum; map<int64,int64>mp; int64 quickPow(int64 m , int64 t){ int64 sum = 1; while(t){ if(t%2 == 1) sum = sum*m%MOD; m = m*m%MOD; t = t/2; } return sum%MOD; } void solve(){ int64 ans = sum; map<int64 , int64>::iterator it; for(it = mp.begin() ; it != mp.end() ; it++){ if(it->second >= x){ mp[(it->first)+1] += (it->second)/x; (it->second) %= x; } if(it->second){ ans = min(ans , it->first); break; } } ans = quickPow(x , ans); cout<<ans<<endl; } int main(){ while(scanf("%d%d" , &n , &x) != EOF){ sum = 0; for(int i = 0 ; i < n ; i++){ scanf("%d" , &num[i]); sum += num[i]; } mp.clear(); for(int i = 0 ; i < n ; i++) mp[sum-num[i]]++; solve(); } return 0; }
D Pair of Numbers
题意:给定n个数,要求找到所有区间[l,r],要求这个区间满足两个条件:区间内有一个数a[j]能够整除区间的任何数,并且r-l最大。输出有几个这样的区间和最大的r-l以及所有满足的区间的左端点
思路:暴力枚举每个数。假设当前数为a[i],那么我们就以a[i]为除数,分别向左边和右边去扩展找到以它为除数的最大的满足区间,这样即可
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int MAXN = 3*100010; int n , num[MAXN]; int ans , out[MAXN]; int l[MAXN] , r[MAXN]; void solve(){ // make left l[1] = 1; for(int i = 2 ; i <= n ; i++){ if(num[i-1]%num[i] == 0){ l[i] = l[i-1]; int tmp = l[i]; while(tmp > 1 && num[tmp-1]%num[i] == 0) tmp--; l[i] = tmp; } else l[i] = i; } // make right r[n] = n; for(int i = n-1 ; i >= 1 ; i--){ if(num[i+1]%num[i] == 0){ r[i] = r[i+1]; int tmp = r[i]; while(tmp < n && num[tmp+1]%num[i] == 0) tmp++; r[i] = tmp; } else r[i] = i; } ans = 0; for(int i = 1 ; i <= n ; i++) ans = max(ans , r[i]-l[i]); // make out int pos = 0; for(int i = 1 ; i <= n ; i++) if(ans == r[i]-l[i]) out[pos++] = l[i]; pos = unique(out , out+pos)-out; printf("%d %d\n%d" , pos , ans , out[0]); for(int i = 1 ; i < pos ; i++) printf(" %d" , out[i]); printf("\n"); } int main(){ while(scanf("%d", &n) != EOF){ for(int i = 1 ; i <= n ; i++) scanf("%d" , &num[i]); solve(); } return 0; }
E Neatness
题意:搜索
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; const int MAXN = 510; int mat[MAXN][MAXN]; int n , sum , pos; bool vis[MAXN][MAXN]; int dir[4][2] = {{-1,0},{0,1},{1,0},{0,-1}}; char forwad[4] = {'U','R','D','L'}; char backwad[4] = {'D','L','U','R'}; char ans[MAXN*10000]; bool isOut(int x , int y){ return (x < 1 || x > n || y < 1 || y > n); } bool check(int x , int y , int d){ while(1){ if(isOut(x , y) || vis[x][y]) return false; if(mat[x][y]) return true; x = x+dir[d][0]; y = y+dir[d][1]; } } void dfs(int x , int y){ if(!mat[x][y]){ mat[x][y] = 1; ans[pos++] = '1'; sum++; } vis[x][y] = true; for(int i = 0 ; i < 4 ; i++){ int tx = x+dir[i][0]; int ty = y+dir[i][1]; if(isOut(tx , ty) || vis[tx][ty] || !check(tx , ty , i)) continue; ans[pos++] = forwad[i]; dfs(tx , ty); ans[pos++] = backwad[i]; } sum--; ans[pos++] = '2'; } int main(){ int x , y; while(scanf("%d%d%d" , &n , &x , &y) != EOF){ sum = 0; for(int i = 1 ; i <= n ; i++){ for(int j = 1 ; j <= n ; j++){ scanf("%d" , &mat[i][j]); sum += mat[i][j]; } } pos = 0; memset(vis , false , sizeof(vis)); dfs(x , y); if(sum){ puts("NO"); } else{ puts("YES"); ans[pos] = '\0'; puts(ans); } } return 0; }