Potato的暑期训练day#1题解 ——毒瘤构造
Potato的暑期訓練day#1 ——毒瘤構造
題目鏈接:
A.https://vjudge.net/problem/HDU-1214
B.https://vjudge.net/problem/CodeForces-1174D
C.https://vjudge.net/problem/CodeForces-1166E
D.https://vjudge.net/problem/HihoCoder-1873
F.https://vjudge.net/problem/CodeForces-1159D
G.https://vjudge.net/problem/CodeForces-1130E
A - 圓桌會議
題意:對一個1,2,3,....n構成的圓桌進行操作,每次只能交換相鄰兩位,提問最少需要多少次操作可以是的這個圓桌的位置轉置,即每個人左邊和右邊的人交換了
思路:考慮1,2,3,4,..n的線性排序經過相鄰交換的操作到達n-k-1 n-k-2 ....3 2 1 n n-1 n-2........ n-k這樣的排序的最少步數,轉化為以上的排序何時逆序對最少,顯然在中間的時候,對于每一段長度為k的逆序對總和可以使用 \(k(k-1)/2\) 計算
代碼:
#include<bits/stdc++.h> using namespace std; int N; int main() {while(scanf("%d",&N) != EOF) {if(N%2 == 0) {printf("%d\n",N/2*(N/2-1));}else {int k = N/2;printf("%d\n",k*(k-1)/2+k*(k+1)/2);}}return 0; }B - Ehab and the Expected XOR Problem
題意:對于n,x要求我們給出一個數組a該數組內任意一段的異或都不為0和x,并且讓這個數組長度盡量長,(數組元素滿足\([1.2^n)\) 的范圍,(1≤n≤18, 1≤x<2^18)
思路:我們考慮這個數組的前綴異或和S(n);我們可以得到這樣一個性質S(i)^S(j) = a(j+1)a(j+2)....a(i) 也就是說我們任意一段的連續異或和都可以表示為他的前綴異或和的異或,那么問題就轉化為我要構造一個S數組,其任意兩個的異或和不為0或者x,我們知道a的范圍滿足\([1.2^n)\) 那么有異或的性質可知任意兩個S不相等(相同的數異或和為0)且S的范圍與a相同,那么我們分為兩種情況,第一種\(x>=2^n\) 即無論我如何異或均不考慮x,那么輸出即為[1.2^n)的所有數,第二種\(x<2^n\) 時我們就不能在S中找出m,n使得m^n = x ,我們知道這個東西對于每一個固定的m的n的解是唯一的所以可以直接掃一遍做m,n的vis輸出即可
代碼:
#include<bits/stdc++.h> using namespace std; const int maxn = (1<<18)+5; int n,x; int S[maxn]; bool vis[maxn]; int main() {scanf("%d%d",&n,&x);int pre;if(x>=(1<<n)) {printf("%d\n",(1<<n) - 1);int len = (1<<n);for(int i = 1;i < len;i++) {if(i == 1) {printf("%d ",i);pre = i;}else {printf("%d ",pre^i);pre = i;}}} else {memset(vis,0,sizeof(vis));printf("%d\n",((1<<n) - 1) / 2 );int len = (1<<n) - 1;int cnt = 0;for(int i = 1;i <= len;i++) {if(!vis[i] && i != x) {S[cnt++] = i;vis[i] = true;int b = i^x;vis[b] = true;}}for(int i = 0;i < cnt;i++) {if(i == 0) {printf("%d ",S[i]);pre = S[i];}else {printf("%d ",pre^S[i]);pre = S[i];}}}return 0; }C - The LCMs Must be Large
題意:對于一個長為n的常數數組,我們有m天,每m天取不同的下標的數做一次LCM, 要求判斷是否存在這樣的數組使得我們每次取出的LCM都大于剩下的數的LCM
思路:考慮到LCM是一個很取決于其中最大的一個數的函數,我們只要能保證我們的m天中任意兩天我們都能夠找到有至少一個公共元素,我們總可以去取一個很大的數使得其大于剩余元素的LCM且不矛盾,所以直接\(O(m^2n)\) 暴力判斷即可
代碼:
#include<bits/stdc++.h> using namespace std; const int maxm = 55; const int maxn = 1e4+5; int m,n; bool vis[maxm][maxn]; int main() {scanf("%d%d",&m,&n);int s,x;memset(vis,0,sizeof(vis));for(int i = 0;i < m;i++) {scanf("%d",&s);for(int j = 0;j < s;j++) {scanf("%d",&x);vis[i][x] = true;}}bool flag;for(int i = 0;i < m;i++) {for(int j = 0;j < m;j++) {if(i != j) {flag = false;for(int k = 1;k <= n && !flag;k++) {if(vis[i][k]&&vis[j][k]) flag = true;}}if(!flag) {printf("impossible\n");return 0;}}}printf("possible\n");return 0; }D - Frog and Portal
題意:有0-200個荷葉,有一只青蛙起始位于標號0的荷葉上,我們很任意知道青蛙到荷葉的方案數滿足斐波那契數列,現在我們給出一個m代表到200的方案數,讓我們通過添加傳送門來達到這個方案數,輸出傳送門的數量和起點終點。
思路:先考慮200之前的幾個位置到200 的方案數,例如199到200為1,198為2,197為3,196為5.....顯然也是滿足斐波那契數列的,我們考慮一個m為7 的情況,我們知道7可以由斐波那契數列中的5+2得到,即196和198兩個位置,現在我們通過構造前面的傳送門來,我們通過奇數傳送門構造,這里我們就取前兩個奇數1,3,但是我們要注意我們總的方案數還要加上到1,3 的方案,所以我們可以在4處放一個到自己的傳送門,這樣就使得到1,3只有一種方案,以此類推我們可以得到所有情況(我們可以大概知道一個數總可以由幾個斐波那契數列的和組成)
代碼:
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll M; ll fib[205]; ll ans[205]; void init() {fib[200] = fib[199] = 1;for(int i = 198;i >= 150;i--) fib[i] = fib[i+1] + fib[i+2]; } int main() {init();int cnt;while(scanf("%lld",&M) != EOF) {if(M == 0) {printf("2\n1 1\n2 1\n");}else {cnt = 0;for(int i = 150;i<=200;i++) {if(M==0) break;if(M - fib[i]>=0) {M-=fib[i];ans[cnt++] = i;}}printf("%d\n",cnt+1);for(int i = 0;i < cnt;i++) {printf("%d %lld\n",2*i + 1,ans[i]);}printf("%d %d\n",2*cnt,2*cnt);}}return 0; }F - The minimal unique substring
題意:給出n,k要求求出一個長度為n的01串其唯一字串的最小長度為k
思路:首先我們先觀察三個串 1010,110110,11101110,答案都是01部分,我們可以下一個結論,形如 abab ( a 中有非負整數個 1 , b 中只有一個 0 )這類的字符串答案恒為 2 ,也就是 k==2 ,然后就是用這類字符串去構造出我們所需的 k 。我們可以嘗試從末尾加一個1,那么之前的串變成了 10101,1101101,111011101,那么答案為010部分。我們可以發現,通過我們末尾添加的1,導致之前部分的 01 與我們末尾添加的1與前面一個0構成的 01 重復,使得之前的部分向后挪一位。于是,我們可以用這一規律去構造出我們想要的k,顯然答案就是末尾部分的01(部分111...10111...10111)滿足 0 的個數加 1 的個數等于 k-1 ,那么對中間的影響(部分111...1011111...110111)往后挪一位也就是我們的答案 k ,最后就是算出這形如 abab 字符串 a 部分中的 1 的個數有多少就行了,設 x 為 a 中 1 的個數,方程為 2*x+1+k-1=n ,化簡為 x=(n-k)/2 ,根據題意 n 與 k 同奇偶,那么 x 也是唯一確定的,最后構造也由此生成。
代碼:
#include<bits/stdc++.h> using namespace std; int main() {int n,k;int x = (n - k) / 2;cin>>n>>k;for(int i=0,j=(n-k)/2;i<n;i++){if(j) cout<<1,j--;else cout<<0,j=(n-k)/2;}return 0; }G - Wrong Answer
題意:對一組數考慮一個區間和*區間長度的最大值,給出一個k,使得真正的最大值和
function find_answer(n, a)# Assumes n is an integer between 1 and 2000, inclusive# Assumes a is a list containing n integers: a[0], a[1], ..., a[n-1]res = 0cur = 0k = -1for i = 0 to i = n-1cur = cur + a[i]if cur < 0cur = 0k = ires = max(res, (i-k)*cur)return res的做法求出的最大值差為k,構造這樣的一組數(1≤n≤2000 and |a|≤1e6.k<=1e9)
思路:我們知道數組長度最大為2000,那么我們就來構造一個長度為2000的數組,其前1998均為0,最后兩位為y<0,x>0,那么要滿足2000(y+x) =k+x,即這兩個答案之間差k,則y=(k-1999x)/2000,要使得y<0,則1e9-1999x為負數,那么我們可以取x=1e6-k%2000;即可
#include<bits/stdc++.h> using namespace std; int main() {int k;scanf("%d",&k);printf("2000\n");for(int i = 1;i<=1998;i++) printf("0 ");int x = 1e6 - k%2000;int y = (k - 1999*x) / 2000;printf("%d %d",y,x); }轉載于:https://www.cnblogs.com/pot-a-to/p/11135027.html
總結
以上是生活随笔為你收集整理的Potato的暑期训练day#1题解 ——毒瘤构造的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python爬虫:其他操作
- 下一篇: 关于pycharm+opencv没有代码