牛客小白月赛2
较水题,手速赛。关键是看题不要看错,这样卡时间。还有手速保持在较快的水准,有意识地训练~
A 数字方阵 > 25663765
随机化生成方阵,修改直到方阵满足条件 (重复3次,都A了)
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <list> #include <stack> #include <vector> #include <set> #include <map> #include <queue> #include <algorithm> #include <iostream> using namespace std; #define ll long long const long maxn=1e6+5; const ll mod=1e9+7; long a[1005][1005]; bool vis[100005]; long n,i,j,sum=0,x,y; set<long>f; bool check() { f.clear(); for (i=1;i<=n;i++) { sum=0; for (j=1;j<=n;j++) sum+=a[i][j]; f.insert(sum); sum=0; for (j=1;j<=n;j++) sum+=a[j][i]; f.insert(sum); } sum=0; for (i=1;i<=n;i++) sum+=a[i][i]; f.insert(sum); sum=0; for (i=1;i<=n;i++) sum+=a[i][n+1-i]; f.insert(sum); if (f.size()!=2*n+2) return false; else return true; } int main() { long p,q,x,y,temp; scanf("%ld",&n); while (1) { sum=0; for (i=1;i<=n;i++) for (j=1;j<=n;j++) { sum++; a[i][j]=sum; } for (i=1;i<=min(n*n,(long)1000);i++) { x=rand()%n+1; y=rand()%n+1; p=rand()%n+1; q=rand()%n+1; temp=a[x][y]; a[x][y]=a[p][q]; a[p][q]=temp; } if (check()) { for (i=1;i<=n;i++) { for (j=1;j<n;j++) printf("%ld ",a[i][j]); printf("%ld\n",a[i][j]); } break; } } return 0; }
另:
对称结构最容易产生相同的行/列/对角线和值
但对称结构最好创建
所以创建对称结构,在这基础上进行微调
A 数字方阵 > 25713373
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cmath> 5 #include <list> 6 #include <stack> 7 #include <vector> 8 #include <set> 9 #include <map> 10 #include <queue> 11 #include <algorithm> 12 #include <iostream> 13 using namespace std; 14 #define ll long long 15 const long maxn=1e4+5; 16 const ll mod=1e9+7; 17 18 long a[maxn][maxn]; 19 long i,j,t,n,sum; 20 set<long>f; 21 22 bool check() 23 { 24 f.clear(); 25 for (i=0;i<n;i++) 26 { 27 sum=0; 28 for (j=0;j<n;j++) 29 sum+=a[i][j]; 30 f.insert(sum); 31 printf("%ld\n",sum); 32 33 sum=0; 34 for (j=0;j<n;j++) 35 sum+=a[j][i]; 36 f.insert(sum); 37 printf("%ld\n",sum); 38 } 39 40 sum=0; 41 for (i=0;i<n;i++) 42 sum+=a[i][i]; 43 f.insert(sum); 44 printf("%ld\n",sum); 45 46 sum=0; 47 for (i=0;i<n;i++) 48 sum+=a[i][n+1-i]; 49 f.insert(sum); 50 printf("%ld\n",sum); 51 52 if (f.size()!=2*n+2) 53 return false; 54 else 55 return true; 56 } 57 58 int main() 59 { 60 scanf("%ld",&n); 61 sum=0; 62 for (i=0;i<n;i++) 63 for (j=0;j<n-1;j++) 64 { 65 sum++; 66 a[i][j]=sum; 67 } 68 for (j=0;j<n;j++) 69 { 70 sum++; 71 a[j][n-1]=sum; 72 } 73 /* 74 for (i=0;i<n;i++) 75 { 76 for (j=0;j<n;j++) 77 { 78 sum++; 79 a[i][j]=sum; 80 } 81 } 82 if (n%2==0) 83 { 84 t=a[0][n-2]; 85 a[0][n-2]=a[0][n-1]; 86 a[0][n-1]=t; 87 } 88 else 89 { 90 sum=0; 91 // 92 } 93 */ 94 for (i=0;i<n;i++) 95 { 96 for (j=0;j<n;j++) 97 { 98 printf("%ld",a[i][j]); 99 if (j==n-1) 100 printf("\n"); 101 else 102 printf(" "); 103 } 104 } 105 // if (!check()) 106 // printf("F\n"); 107 return 0; 108 }
B 小马过河 > 25648307
想不到好方法。做了两条直线(ax+by+c=0),求交点
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <list> #include <stack> #include <vector> #include <set> #include <map> #include <queue> #include <algorithm> #include <iostream> using namespace std; #define ll long long const long maxn=1e6+5; const ll mod=1e9+7; long double xp,yp,xu,yu,xv,yv, x,y; long double a1,b1,c1,a2,b2,c2,aa1,bb1,cc1,aa2,bb2,cc2; int main() { long t; scanf("%ld",&t); while (t--) { scanf("%llf%llf%llf%llf%llf%llf",&xp,&yp,&xu,&yu,&xv,&yv); a1=yu-yv; b1=xv-xu; c1=-a1*xu-b1*yu; a2=xu-xv; b2=yu-yv; c2=-a2*xp-b2*yp; aa1=a1*a2; bb1=b1*a2; cc1=c1*a2; aa2=a2*a1; bb2=b2*a1; cc2=c2*a1; y=(cc1-cc2)/(bb2-bb1); x=(-c1-b1*y)/a1; printf("%.7llf %.7llf\n",x,y); } return 0; }
另:直接推公式
https://blog.csdn.net/sr_19930829/article/details/19825661
C 真真假假 > 25645450
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <list> #include <stack> #include <vector> #include <set> #include <map> #include <queue> #include <algorithm> #include <iostream> using namespace std; #define ll long long const long maxn=1e6+5; const ll mod=1e9+7; char str[35][20]={"algorithm", "bitset", "cctype", "cerrno", "clocale", "cmath", "complex", "cstdio", "cstdlib", "cstring", "ctime", "deque", "exception", "fstream", "functional", "limits", "list", "map", "iomanip", "ios", "iosfwd", "iostream", "istream", "ostream", "queue", "set", "sstream", "stack", "stdexcept", "streambuf", "string", "utility", "vector", "cwchar", "cwctype"}; char s[1000]; void pan() { long i; for (i=0;i<35;i++) if (strcmp(s,str[i])==0) { printf("Qian\n"); return; } printf("Kun\n"); } int main() { long t; scanf("%ld\n",&t); while (t--) { gets(s); pan(); } return 0; }
比赛时候不停“”,太傻,幸好数量不多
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cmath> 5 #include <list> 6 #include <stack> 7 #include <vector> 8 #include <set> 9 #include <map> 10 #include <queue> 11 #include <algorithm> 12 #include <iostream> 13 using namespace std; 14 #define ll long long 15 const long maxn=1e6+5; 16 const ll mod=1e9+7; 17 18 19 int main() 20 { 21 char s[20]; 22 while (scanf("%s",s)!=EOF) 23 { 24 s[strlen(s)-1]='\0'; 25 printf("\"%s\",",s); 26 } 27 return 0; 28 }
D 虚虚实实 > 25650110
看得很懵的题目,这告诫我看完题顺便再看看测试数据
其实就是求一笔画问题
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <list> #include <stack> #include <vector> #include <set> #include <map> #include <queue> #include <algorithm> #include <iostream> using namespace std; #define ll long long const long maxn=1e6+5; const ll mod=1e9+7; vector<long> p[35]; bool vis[35]; long ans,wrong,n,g[35]; void dfs(long d) { vis[d]=true; ans++; vector<long>::iterator j; for (j=p[d].begin();j!=p[d].end();j++) if (!vis[*j]) dfs(*j); } int main() { long t,m,i,x,y; scanf("%ld",&t); while (t--) { scanf("%ld%ld",&n,&m); for (i=1;i<=n;i++) { p[i].clear(); vis[i]=false; g[i]=0; } for (i=1;i<=m;i++) { scanf("%ld%ld",&x,&y); g[x]++; g[y]++; p[y].push_back(x); p[x].push_back(y); } ans=0; dfs(1); wrong=0; for (i=1;i<=n;i++) if (g[i]%2==1) wrong++; if (ans==n && wrong<=2) printf("Zhen\n"); else printf("Xun\n"); } return 0; }
E 是是非非 > 25653790
nim问题。好像有升级版https://blog.csdn.net/acm_baihuzi/article/details/41622825
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <list> #include <stack> #include <vector> #include <set> #include <map> #include <queue> #include <algorithm> #include <iostream> using namespace std; #define ll long long const long maxn=1e5+5; const ll mod=1e9+7; long a[maxn]; int main() { long n,t,v,x,y,i; scanf("%ld%ld",&n,&t); v=0; for (i=1;i<=n;i++) { scanf("%ld",&a[i]); v=v ^ a[i]; } while (t--) { scanf("%ld%ld",&x,&y); v=v ^ a[x]; a[x]=y; v=v ^ a[x]; if (v==0) printf("Li\n"); else printf("Kan\n"); } return 0; }
F 黑黑白白 > 25653038
树上的博弈论。从叶子到根。
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cmath> 5 #include <list> 6 #include <stack> 7 #include <vector> 8 #include <set> 9 #include <map> 10 #include <queue> 11 #include <algorithm> 12 #include <iostream> 13 using namespace std; 14 #define ll long long 15 const long maxn=1e4+5; 16 const ll mod=1e9+7; 17 18 vector<long> p[maxn]; 19 bool vis[maxn],v[maxn][2]; 20 long fa[maxn]; 21 22 void dfs(long d) 23 { 24 vis[d]=true; 25 vector<long>::iterator j; 26 bool leap=true; 27 for (j=p[d].begin();j!=p[d].end();j++) 28 if (!vis[*j]) 29 { 30 dfs(*j); 31 leap=false; 32 } 33 else 34 fa[d]=*j; 35 if (leap) 36 { 37 v[d][0]=true; //oven step 38 v[d][1]=false; //odd 39 } 40 else 41 { 42 v[d][0]=false; //oven step 43 v[d][1]=false; //odd 44 for (j=p[d].begin();j!=p[d].end();j++) 45 if (fa[d]!=*j) 46 { 47 if (!v[*j][1]) 48 v[d][1]=true; 49 if (!v[*j][0]) 50 v[d][0]=true; 51 } 52 } 53 } 54 55 int main() 56 { 57 long t,n,m,i,x,y,r; 58 scanf("%ld",&t); 59 while (t--) 60 { 61 scanf("%ld%ld",&n,&r); 62 for (i=1;i<=n;i++) 63 { 64 p[i].clear(); 65 vis[i]=false; 66 } 67 for (i=1;i<n;i++) 68 { 69 scanf("%ld%ld",&x,&y); 70 p[y].push_back(x); 71 p[x].push_back(y); 72 } 73 fa[r]=r; 74 dfs(r); 75 76 if (v[r][1]) 77 printf("Gen\n"); 78 else 79 printf("Dui\n"); 80 } 81 return 0; 82 }
G 文 > 25646203
只用保存最大的状态。
选择题答卷用char输入,一一比对会快一点
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cmath> 5 #include <list> 6 #include <stack> 7 #include <vector> 8 #include <set> 9 #include <map> 10 #include <queue> 11 #include <algorithm> 12 #include <iostream> 13 using namespace std; 14 #define ll long long 15 const long maxn=1e6+5; 16 const ll mod=1e9+7; 17 18 char answer[100005],name[100],maxname[100]; 19 20 int main() 21 { 22 long n,m,maxr,r,i,j; 23 char c; 24 scanf("%ld%ld",&n,&m); 25 scanf("%s",answer); 26 maxr=-1; 27 strcpy(name,""); 28 for (i=1;i<=m;i++) 29 { 30 scanf("%s\n",name); 31 r=0; 32 for (j=0;j<n;j++) 33 { 34 scanf("%c",&c); 35 if (c==answer[j]) 36 r++; 37 } 38 if (r>maxr || (r==maxr && strcmp(name,maxname)<0)) 39 { 40 maxr=r; 41 strcpy(maxname,name); 42 } 43 } 44 printf("%s\n",maxname); 45 printf("%.2lf\n",100.0*maxr/n); 46 return 0; 47 }
H 武 > 25713562
求最短路,从s点出发的第k小距离
priority_queue里的符号老是写反……
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cmath> 5 #include <list> 6 #include <stack> 7 #include <vector> 8 #include <set> 9 #include <map> 10 #include <queue> 11 #include <algorithm> 12 #include <iostream> 13 using namespace std; 14 #define ll long long 15 const long maxn=1e5+5; 16 const ll mod=1e9+7; 17 #define inf 1e9 18 vector<pair<long,long> > p[maxn]; 19 long dist[maxn]; 20 bool vis[maxn]; 21 22 struct cmp 23 { 24 bool operator() (int a,int b) 25 { 26 return dist[a]>dist[b]; //opposite 27 } 28 }; 29 30 priority_queue<int,vector<int>,cmp> f; 31 32 int main() 33 { 34 long n,d,k,i,x,y,z; 35 vector<pair<long,long> >::iterator j; 36 scanf("%ld%ld%ld",&n,&d,&k); 37 for (i=1;i<=n;i++) 38 { 39 p[i].clear(); 40 dist[i]=inf; 41 vis[i]=false; 42 } 43 dist[d]=0; 44 45 for (i=1;i<n;i++) 46 { 47 scanf("%ld%ld%ld",&x,&y,&z); 48 p[x].push_back(make_pair(y,z)); 49 p[y].push_back(make_pair(x,z)); 50 } 51 f.push(d); 52 53 for (i=1;i<=k+1;i++) 54 { 55 while (vis[f.top()]) 56 f.pop(); 57 d=f.top(); 58 vis[d]=true; 59 f.pop(); 60 for (j=p[d].begin();j!=p[d].end();j++) 61 if (!vis[j->first] && dist[j->first]>dist[d]+j->second) 62 { 63 dist[j->first] = dist[d]+j->second; 64 f.push(j->first); 65 } 66 } 67 printf("%ld",dist[d]); 68 return 0; 69 }
另: 树结构,根到某个节点的路径和路径长度唯一确定
可以优化,不过像题解说的O(n)是不可能的,如所有点仅与根节点相连
H 武 > 25713622
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cmath> 5 #include <list> 6 #include <stack> 7 #include <vector> 8 #include <set> 9 #include <map> 10 #include <queue> 11 #include <algorithm> 12 #include <iostream> 13 using namespace std; 14 #define ll long long 15 const long maxn=1e5+5; 16 const ll mod=1e9+7; 17 #define inf 1e9 18 vector<pair<long,long> > p[maxn]; 19 long dist[maxn]; 20 bool vis[maxn]; 21 22 struct cmp 23 { 24 bool operator() (int a,int b) 25 { 26 return dist[a]>dist[b]; //opposite 27 } 28 }; 29 30 priority_queue<int,vector<int>,cmp> f; 31 32 int main() 33 { 34 long n,d,k,i,x,y,z; 35 vector<pair<long,long> >::iterator j; 36 scanf("%ld%ld%ld",&n,&d,&k); 37 for (i=1;i<=n;i++) 38 { 39 p[i].clear(); 40 dist[i]=inf; 41 vis[i]=false; 42 } 43 dist[d]=0; 44 45 for (i=1;i<n;i++) 46 { 47 scanf("%ld%ld%ld",&x,&y,&z); 48 p[x].push_back(make_pair(y,z)); 49 p[y].push_back(make_pair(x,z)); 50 } 51 f.push(d); 52 53 for (i=1;i<=k+1;i++) 54 { 55 d=f.top(); 56 vis[d]=true; 57 f.pop(); 58 for (j=p[d].begin();j!=p[d].end();j++) 59 if (!vis[j->first]) 60 { 61 dist[j->first] = dist[d]+j->second; 62 f.push(j->first); 63 } 64 } 65 printf("%ld",dist[d]); 66 return 0; 67 }
I 艺 > 25665565
取每个节目的开始时间和 最后结束时间,时间从小到大,在某一个时间内,两个电视分别播一个特定的节目,取最大值,若最大值小于0,不取,否则取。
调了很久,最后发现sort的变量写错了(n->m),看来程序写错了也不行一昧地调试,重新看一遍代码,会发现调试难以发现的错误……
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cmath> 5 #include <list> 6 #include <stack> 7 #include <vector> 8 #include <set> 9 #include <map> 10 #include <queue> 11 #include <algorithm> 12 #include <iostream> 13 using namespace std; 14 #define ll long long 15 const long maxn=1e5+5; 16 const ll mod=1e9+7; 17 #define inf 1e9 18 19 struct node 20 { 21 long long x,v; 22 }f1[maxn],f2[maxn]; 23 24 bool cmp(node a,node b) 25 { 26 return a.x<b.x; 27 } 28 29 int main() 30 { 31 long n,m,t,i,j,a,b; 32 long long ans=0,v,x,prex; 33 scanf("%ld%ld%ld",&n,&m,&t); 34 35 for (i=1;i<=n;i++) 36 scanf("%lld%lld",&f1[i].x,&f1[i].v); 37 sort(f1+1,f1+n+1,cmp); 38 f1[n+1].x=t; f1[n+1].v=0; n++; 39 f1[n+2].x=inf; 40 41 for (i=1;i<=m;i++) 42 scanf("%lld%lld",&f2[i].x,&f2[i].v); 43 sort(f2+1,f2+m+1,cmp); 44 f2[m+1].x=t; f2[m+1].v=0; m++; 45 f2[m+2].x=inf; 46 47 a=1; b=1; x=0; i=1; j=1; 48 while (a<=n || b<=m) 49 { 50 //one+two pointers 51 52 //find next time 53 prex=x; 54 if (f1[a].x<f2[b].x) 55 { 56 x=f1[a].x; 57 a++; 58 } 59 else if (f1[a].x>f2[b].x) 60 { 61 x=f2[b].x; 62 b++; 63 } 64 else 65 { 66 x=f1[a].x; 67 a++; 68 b++; 69 } 70 71 //find the value that is smaller that x, whose program can be watches at time x 72 while (f1[i+1].x<x) 73 i++; 74 while (f2[j+1].x<x) 75 j++; 76 77 v=max(f1[i].v,f2[j].v); 78 if (v>0) 79 ans+=(x-prex)*v; 80 } 81 printf("%lld\n",ans); 82 return 0; 83 } 84 /* 85 1 2 5 86 0 3 87 0 1 88 2 5 89 25 90 */
J 美 > 25656447
贪心。排序后(a[1],a[2],…,a[n]从小到大),a[1] -> a[n] th -> a[2] th -> a[n-1] th -> ……
比赛时没证明就直接写了,发现对了,感觉。。。
证明:
环结构,每个数Ri都重复计算了两遍,去掉绝对值,2*n次计算中,n次减,n次加。要想值最大,则大值尽量地加,小值尽量地减。
即a[1]~a[n/2]减两次;a[(n+1)/2+1]~a[n]加两次。如果n为奇数,则a[n/2+1]加一次,减一次。
a[1] -> a[n] th -> a[2] th -> a[n-1] th -> ……正好满足条件,得证。
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cmath> 5 #include <list> 6 #include <stack> 7 #include <vector> 8 #include <set> 9 #include <map> 10 #include <queue> 11 #include <algorithm> 12 #include <iostream> 13 using namespace std; 14 #define ll long long 15 const long maxn=1e5+5; 16 const ll mod=1e9+7; 17 18 long long a[maxn],b[maxn]; 19 20 int main() 21 { 22 long n,i,x,y; 23 long long ans=0; 24 scanf("%ld",&n); 25 for (i=1;i<=n;i++) 26 { 27 scanf("%lld",&a[i]); 28 } 29 sort(a+1,a+n+1); 30 31 x=1; 32 y=n; 33 for (i=1;i<=n;i++) 34 { 35 if (i%2==0) 36 { 37 b[i]=a[x]; 38 x++; 39 } 40 else 41 { 42 b[i]=a[y]; 43 y--; 44 } 45 } 46 47 ans=0; 48 for (i=2;i<=n;i++) 49 ans+=abs(b[i]-b[i-1]); 50 ans+=abs(b[n]-b[1]); 51 52 printf("%lld\n",ans); 53 return 0; 54 }