/*name: Repdigit Numberid: AT_arc149_adate: 2023/01/23
*/#include
using namespace std;
typedef long long ll;int n, m, a, b;int main(){scanf("%d%d", &n, &m);ll p = 0;for(int i = 1; i <= n; ++ i){p = (p * 10 + 1);ll r = p % m;p %= m;for(int j = 1; j <= 9; ++ j){if(r * j % m == 0){a = i, b = j;}}}if(!a){puts("-1");} else {for(int i = 1; i <= a; ++ i){putchar(b + '0');}puts("");}return 0;
}
/*name: Two LIS Sumid: AT_arc149_bdate: 2023/01/24
*/#include
using namespace std;const int N = 3e5 + 10;
int n, a[N], b[N], st[N], top;int main(){scanf("%d", &n);for(int i = 1; i <= n; ++ i){scanf("%d", &b[i]);}for(int i = 1; i <= n; ++ i){scanf("%d", &a[b[i]]);}st[++top] = a[1];for(int i = 2; i <= n; ++ i){if(st[top] < a[i]){st[++top] = a[i];} else {int k = lower_bound(st + 1, st + top + 1, a[i]) - st;st[k] = a[i];}}printf("%d\n", top + n);return 0;
}
显然奇+奇为合数,偶+偶为合数,所以我们可以将上半部分填满奇数,下半部分填满偶数,然后只用考虑两部分交界的地方了。
如果 nnn 为偶数,那么可以直接枚举出来一个值域在 [2n,n2][2n, n^2][2n,n2] 的奇合数,然后把相加为这个数的二元组填到交界处。
如果 nnn 为奇数,那么边界会在中间有个拐弯,那么就在中间构造一个一下结构(111 在正中心):
7 | ||
---|---|---|
8 | 1 | |
14 |
3∗33*33∗3 没有 141414,那就特判一下。
那么接着和上面一样填就好了。注意的是枚举奇合数从小往大可能会有问题(已经用了四个小的数),改成从大往小枚举就行了。
/*name: Avoid Prime Sumid: AT_arc149_cdate: 2023/01/24
*/#include
using namespace std;const int N = 1010;
int n, vis[N*N], a[N][N];bool isp(int k){for(int i = 2; i * i <= k; ++ i){if(k % i == 0){return false;}}return true;
}int main(){scanf("%d", &n);if(n == 3){a[1][1] = 1;a[1][2] = 9;a[1][3] = 3;a[2][1] = 8;a[2][2] = 7;a[2][3] = 5;a[3][1] = 6;a[3][2] = 2;a[3][3] = 4;} else if(n & 1){int k = n / 2 + 1;a[k][k] = 1;a[k][k-1] = 8;a[k-1][k-1] = 7;a[k+1][k] = 14;vis[1] = vis[7] = vis[8] = vis[14] = 1;for(int i = n * n; i >= n + n; -- i){if((i & 1) && !isp(i)){int now = 2;for(int j = 1; j <= n; ++ j){int pos = j < k ? k-1 : k;if(a[pos][j]) continue;while(vis[now] || vis[i-now]) ++ now;if(now & 1){a[pos][j] = now;a[pos+1][j] = i - now;} else {a[pos][j] = i - now;a[pos+1][j] = now;}vis[now] = vis[i-now] = 1;}break;}}int tot1 = 1, tot2 = 2;for(int i = 1; i < k; ++ i){for(int j = 1; j <= n; ++ j){if(!a[i][j]){while(vis[tot1]){tot1 += 2;}a[i][j] = tot1;vis[tot1] = 1;}}}for(int i = k + 1; i <= n; ++ i){for(int j = 1; j <= n; ++ j){if(!a[i][j]){while(vis[tot2]){tot2 += 2;}a[i][j] = tot2;vis[tot2] = 1;}}}} else {for(int i = n + n; i <= n * n; ++ i){if((i & 1) && !isp(i)){for(int j = 1; j <= n; ++ j){if(j & 1){a[n/2][j] = j;a[n/2+1][j] = i - j;} else {a[n/2][j] = i - j;a[n/2+1][j] = j;}vis[j] = vis[i-j] = 1;}break;}}int tot1 = 1, tot2 = 2;for(int i = 1; i < n / 2; ++ i){for(int j = 1; j <= n; ++ j){if(!a[i][j]){while(vis[tot1]){tot1 += 2;}a[i][j] = tot1;vis[tot1] = 1;}}}for(int i = n / 2 + 2; i <= n; ++ i){for(int j = 1; j <= n; ++ j){if(!a[i][j]){while(vis[tot2]){tot2 += 2;}a[i][j] = tot2;vis[tot2] = 1;}}}}for(int i = 1; i <= n; ++ i){for(int j = 1; j <= n; ++ j){printf("%d ", a[i][j]);}puts("");}return 0;
}
考虑求解区间 [1,106][1,10^6][1,106] 的答案。
发现如果某个时刻,两个点所在位置互为相反数,那么两个点的答案也肯定互为相反数。所以我们可以在每次移动区间的时候只保留原点右侧或左侧的一个区间,易得这个区间是连续的。最后计算完 dfs 一下就能得到每个点的结果。
/*name: Simultaneous Sugorokuid: AT_arc149_ddate: 2023/01/24
*/#include
using namespace std;const int N = 3e5 + 10, M = 1e6 + 10;
int n, m, x[N], d, ans[M], stop[M];
vector g[M];void dfs(int x, int v, int op){stop[x] = op;ans[x] = v;for(int i : g[x]){dfs(i, -v, op);}
}int main(){scanf("%d%d", &n, &m);for(int i = 1; i <= n; ++ i){scanf("%d", &x[i]);}int l = 1, r = 1000000, tag = 0;for(int i = 1; i <= m; ++ i){scanf("%d", &d);int mid;tag += d * (l + tag > 0 ? -1 : 1);mid = -tag;if(l <= mid && mid <= r){stop[mid] = i;if(mid - l > r - mid){for(int j = r; j > mid; -- j){g[mid*2-j].push_back(j);}r = mid - 1;} else {for(int j = l; j < mid; ++ j){g[mid*2-j].push_back(j);}l = mid + 1;}}}for(int i = 1; i <= 1000000; ++ i){if(stop[i]){dfs(i, 1, stop[i]);}}for(int i = l; i <= r; ++ i){ans[i] = i + tag;dfs(i, ans[i], 0);}for(int i = 1; i <= n; ++ i){if(stop[x[i]]){printf("Yes %d\n", stop[x[i]]);} else {printf("No %d\n", ans[x[i]]);}}return 0;
}
首先把问题转化为:把 a0,1,...,m−2a_{0,1,...,m-2}a0,1,...,m−2 作为一个集合,am−1,m,...,na_{m-1,m,...,n}am−1,m,...,n 作为队列,进行 kkk 次操作每次把队首放入集合,并取出集合内最小值放入队尾。
设 r=n−m+1r=n-m+1r=n−m+1,则若 k=rk=rk=r,kkk 次操作后左边集合变为 {r+1,r+2,...,n}\{r+1,r+2,...,n\}{r+1,r+2,...,n},右边记为 (x1,x2,...,xr)(x_1,x_2,...,x_r)(x1,x2,...,xr)。如果左边集合不为 {r+1,r+2,...,n}\{r+1,r+2,...,n\}{r+1,r+2,...,n} 则无解。
接下来考虑 xxx 数组,如果存在 xi−1>xix_{i-1}>x_ixi−1>xi,那么这个 xix_ixi 就只有一种可能位置(因为此时的集合的数必定都大于 xi−1x_{i-1}xi−1,从而大于 xix_ixi)。否则有 1+(m−1)=m1+(m-1)=m1+(m−1)=m 种可能位置。
因为集合是无序的,答案应该乘上 (m−1)!(m-1)!(m−1)!。
如果 k>rk>rk>r,那么 [r+1,r+2,...,k][r+1,r+2,...,k][r+1,r+2,...,k] 的操作其实相当于对于右边的队列循环左移,可以转化为 k=rk=rk=r 的问题。
如果 k/*name: Sliding Window Sortid: AT_arc149_edate: 2023/01/24
*/#include
F.RationalNumberSystem−\color{#FF0000}\texttt{F. } \color{#965B2B}\texttt{Rational Number System}\color{grey}~-F. Rational Number System −
上一篇:【头歌】单链表的排序操作
下一篇:信息论复习—连续信源、信道及容量