Test on 11/24/2018
偶然间最糟糕的再会
Description
Input
Output
对于每行输出一个整数
Examples
Input
1 4 2 3 4 1 1 3 4 2
Output
3
正确解法:
官方题解:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int a[200005],b[200005]; 5 int conv[200005]; 6 int main() 7 { 8 freopen("stdin.txt","r",stdin); 9 freopen("stdout.txt","w",stdout); 10 int zu; 11 scanf("%d",&zu); 12 while(zu--) 13 { 14 int n; 15 scanf("%d",&n); 16 for(int i=1;i<=n;i++) scanf("%d",&a[i]),conv[a[i]]=i; 17 for(int i=1;i<=n;i++) scanf("%d",&b[i]); 18 ll ans=0; 19 for(int i=1;i<=n;i++) ans+=abs(i-conv[b[i]]); 20 printf("%lld\n",ans/2); 21 } 22 }
(为什么这样写我也不知道qaq)
01串
Description
现在我们有一个由01组成的字符串。我们需要在上面做一些操作。每次我们都选一个“01”子串,把他替换成110。如果找不到“01”子串,那么操作结束。请输出总共进行了多少次操作,结果请mod 1e9+7。
Ps:“01”子串必须是相邻的0和1,字符串中只包含0和1。
Input
首先一个T,代表接下来有T行。
接下来的T行,每行一个字符串str
(1<= T <= 200, 所有字符串长度和 len <= 2e7)
Output
对于每个字符串,输出相应操作数。
Examples
Input
2 01 001
Output
1
3
正确解法:
每个字符串都会变成前面是1,后面是0,若在1前面有一个0,那么需要1次。有两个0,需要3次,有n个0,需要(2*n-1)次,若有两个1,你会发现,第一个1变化后,所以第一个1前面的0都变到了第二个1的前面。
所有就统计0个个数,遇到1就加一次。
粗题⼈不考你没学过的算法
Description
粗题⼈症重承诺此题不考你没学过的算法
给你⼀个区间[L,R]
需要选择N个数,这N个数都在这个区间范围内
那么我们知道⼀共有[R-L+1]^N种选法
假如我们想要这N个数的最⼤公约数恰好是K
Input
多组测试数据 对于每组数据,输⼊⼀⾏包含4个整数N,K,L,R(1<=N,K,L<=10^9,L<=R<=10^9)
(0<=R-L<=10^5)
Output
对于每行输出一个整数
Examples
Input
2 2 2 4 2 100 2 4 1 5 5 5 73824 17347 9293482 9313482 222 222 222 22222
Output
3 0 1 0 339886855
正确解法:
不会qaq 挖坑。
1 #include <iostream> 2 #include <fstream> 3 #include <sstream> 4 #include <cstdio> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cmath> 8 #include <ctime> 9 #include <algorithm> 10 #include <vector> 11 #include <queue> 12 #include <deque> 13 #include <stack> 14 #include <set> 15 #include <map> 16 #include <complex> 17 #include <bitset> 18 #include <iomanip> 19 #include <utility> 20 21 using namespace std; 22 23 typedef long long LL; 24 typedef pair<int,int> pii; 25 typedef complex<double> point; 26 27 const int mod = 1000000007; 28 29 int f[200000]; 30 31 int POW (int base, int p){ 32 int ret = 1, cur = base; 33 while (p){ 34 if (p & 1) ret = (LL)ret * cur % mod; 35 p>>=1; 36 cur = (LL)cur * cur % mod; 37 } 38 return ret; 39 } 40 41 struct RandomGCD{ 42 int countTuples(int N, int K, int lo, int hi){ 43 memset(f, 0, sizeof(f)); 44 lo = (lo+K-1)/K, hi = hi/K; 45 if (lo > hi) 46 return 0; 47 for (int i=100000; i>=1; i--){ 48 int L = (lo + i-1) / i; 49 int H = hi / i; 50 if (L <= H){ 51 f[i] = POW(H-L+1, N); 52 f[i]-= (H-L+1); 53 if (f[i] < 0) f[i]+= mod; 54 for (int j=i*2; j<=100000; j+=i){ 55 f[i]-=f[j]; 56 if (f[i]<0) f[i]+= mod; 57 } 58 } 59 } 60 if (lo == 1) 61 f[1] = (f[1] + 1) % mod; 62 return f[1]; 63 } 64 }; 65 66 int main() { 67 RandomGCD test; 68 int N, K, L, R; 69 while (cin >> N >> K >> L >> R) { 70 cout << test.countTuples(N, K, L, R) << endl; 71 } 72 return 0; 73 }
平方排列
Description
Input
Output
如果存在这样的排列(如果存在多个,输出字典序最小的),输出n个以空格隔开的整数表示这个排列,否则输出-1。
Examples
Input
1
Output
1
正确解法:
这题想一想就知道,只有1和15.
但我们还是要用dfs,我还是不熟啊,变量有点多,有点复杂。
1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<map> 6 #include<algorithm> 7 #include<cmath> 8 using namespace std; 9 int n,a[20], book[20], flag = 0; 10 void dfs(int k) 11 { 12 if (k == n + 1) 13 { 14 flag = 1; 15 for (int i = 1; i < n; i++) 16 cout << a[i] << " "; 17 cout << a[n] << endl; 18 return ; 19 } 20 for (int i = 1; i <= n; i++) 21 { 22 int tmp = (int)sqrt(i + a[k - 1]); 23 if (k>1&&i + a[k - 1] != tmp * tmp) 24 continue; 25 if (book[i] == 0&&flag==0) 26 { 27 book[i] = 1; 28 a[k] = i; 29 dfs(k + 1); 30 book[i] = 0; 31 } 32 } 33 } 34 int main() 35 { 36 flag = 0; 37 cin >> n; 38 dfs(1); 39 if (flag == 0) cout << -1 << endl; 40 return 0; 41 }
除了第一个数,保证后面的数都与前面的数形成平方数。
最后找到n个输出就好了。
四色图
Description
Perfectxx给LZH出了一道题,要LZH构造出一个尽可能大的四色图。所谓的四色图指的是由n个点m条边组成的无向图。其中,每个点要么是红色,要么是蓝色,每条边要么是黑色,要么是白色。
黑边能连接两个红点,或是一个红点与一个蓝点。而白边只能连接红点与蓝点。
LZH构造出了一个图,但是委托给Murphyc,让他去打印的时候,Murphyc用了黑白打印机。现在分不清楚顶点的颜色是红还是蓝。
现在你需要帮Perfectxx检查一下,LZH构造出的图有没有可能是四色图。
Input
第一行输入n和m,表示点的数量和边的数量 (1<=n,m<=2e5)
接下来的m行,每行三个输入 w u v 表示图中有一条从u到v的无向边,w=1时表示
这条边是黑边,w=0是表示这条边是白边。
Output
仅输出一行字符串,其中”Maybe”表示原图有可能是四色图,”Impossible”表示原图一定不是四色图。(输出中没有引号)
Examples
Input
4 4 0 1 2 0 2 3 0 3 4 0 4 1 3 3 0 1 2 0 2 3 0 3 1
Output
Maybe Impossible
正确解法:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=500000; 4 int ins[N],dfn[N],low[N],cnt,sta[N]; 5 int top,v,u; 6 int Next[N],head[N],to[N]; 7 int tot; 8 int scc[N]; 9 int scccnt; 10 void make_list(int u,int v){ 11 Next[++tot]=head[u],head[u]=tot,to[tot]=v; 12 } 13 void tarjan(int x){ 14 ins[x]=dfn[x]=low[x]=++cnt,sta[top++]=x; 15 for(int p=head[x],v=to[p];p;p=Next[p],v=to[p]) 16 if(!dfn[v])tarjan(v),low[x]=min(low[x],low[v]); 17 else if(ins[v])low[x]=min(low[x],dfn[v]); 18 if(low[x]==dfn[x]){ 19 scc[x]=++scccnt,ins[x]=0; 20 while((u=sta[--top])!=x)ins[u]=0,scc[u]=scccnt; 21 } 22 } 23 int main(){ 24 int n,m,w,u,v; 25 freopen("data5.in","r",stdin); 26 freopen("data5.out","w",stdout); 27 scanf("%d%d",&n,&m); 28 for(int i=1;i<=m;i++){ 29 scanf("%d%d%d",&w,&u,&v); 30 if(!w){ 31 make_list(u,v+n); 32 make_list(v,u+n); 33 make_list(u+n,v); 34 make_list(v+n,u); 35 } 36 else{ 37 make_list(u+n,v); 38 make_list(v+n,u); 39 } 40 } 41 42 for(int i=1;i<=2*n;i++){ 43 if(!dfn[i])tarjan(i); 44 } 45 bool ok=1; 46 for(int i=1;i<=n;i++){ 47 ok&=(scc[i]!=scc[i+n]); 48 } 49 if(ok)puts("Maybe"); 50 else puts("Impossible"); 51 return 0; 52 }
最大化
Description
给你n个整数,请重新排列这些整数,使得式子的值最大,其中表示第i个整数。请输出S的最大值。
Input
第一行一个整数n(2 <= n <= 100000),表示数字的个数;
第二行为n个整数 (1 <= ai <= 1000000000)
Output
输出一个整数,表示S的最大值。
Examples
Input
2 2 1
Output
1
正确解法:
Smax = (-1)^2 * (2 – 1) = 1
简单模拟一下,找到奇数和偶数的不同
1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<map> 6 #include<algorithm> 7 #include<cmath> 8 using namespace std; 9 int n; 10 long long a[100100],sum=0; 11 int main() 12 { 13 cin >> n; 14 for (int i = 1; i <= n; i++) 15 cin >> a[i]; 16 sort(a + 1, a + n + 1); 17 if (n % 2 == 0) 18 { 19 for (int i = n / 2 + 1; i <= n; i++) 20 sum += 2*a[i]; 21 for (int i = 1; i <= n / 2; i++) 22 sum -= 2*a[i]; 23 sum = sum - a[n / 2 + 1] +a[n / 2]; 24 } 25 else 26 { 27 for (int i = n / 2 + 2; i <= n; i++) 28 sum += 2*a[i]; 29 for (int i = 1; i <= n / 2; i++) 30 sum -= 2*a[i]; 31 sum = sum - a[n / 2 + 1] - a[n / 2 - 2]; 32 } 33 cout << sum << endl; 34 return 0; 35 }
调整队列
Description
Input
第一行一个整数n(2 <= n <= 100000),表示数列中数的个数;
第二行为n个整数pi (1 <= pi <= 1e9)。
Output
输出一个整数,表示操作数量的最小值。如果不存在则输出-1。
Examples
Input
4 24 21 14 10 2 500 500 3 14 5 1 5 1 3 6 9 12
Output
3 0 -1 1
正确解法:
暴力搜索qaq,不够熟悉,再见!
1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<map> 6 #include<algorithm> 7 #include<cmath> 8 using namespace std; 9 int n, a[100100],ans=-1; 10 void dfs(int k, int c, int d) 11 { 12 if (k >= n + 1) 13 { 14 if (ans == -1) 15 ans = c; 16 else ans = min(ans,c); 17 return; 18 } 19 for (int i = -1; i <= 1; i++) 20 { 21 if (a[k] + i - a[k - 1] == d) 22 { 23 a[k] += i; 24 dfs(k + 1, c + abs(i), d); 25 a[k] -= i; 26 } 27 } 28 } 29 int main() 30 { 31 while (cin >> n) 32 { 33 ans = -1; 34 for (int i = 1; i <= n; i++) 35 cin >> a[i]; 36 for (int i = -1; i <= 1; i++) 37 { 38 a[1] += i; 39 for (int j = -1; j <= 1; j++) 40 { 41 a[2] += j; 42 dfs(3, abs(i) + abs(j), a[2] - a[1]); 43 a[2] -= j; 44 } 45 a[1] -= i; 46 } 47 cout << ans << endl; 48 } 49 return 0; 50 }