第六场各种数论题,对此没什么想写的(知道结论就是20行的事,无多少意义)故从第七场开始写
1001Hyperspace
曼哈顿距离多次求解,用2^k来维护最大最小值既能得解
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <string> #include <vector> #include <queue> #include <map> using namespace std; #define clr(a, x) memset(a, x, sizeof(a)) #define rep(i, n) for (int i = 0; i < (int)(n); i++) #define REP(i,a,b) for(int i=a;i<=b;i++) const int maxn = 60005; struct node { int d; int id; bool operator<(const pp a)const { return d<a.d; } }; bool vis[maxn]; int p[10]; int main() { int n,k; while(~scanf("%d %d",&n,&k)) { priority_queue<pp>pq[1<<k]; clr(vis,0); int all=(1<<k)-1; for(int i=1; i<=n; i++) { int op; scanf("%d",&op); if(op) { int del; scanf("%d",&del); vis[del]=1; } else { for(int j=0; j<k; j++) scanf("%d",&p[j]); for(int s=0; s<=all; s++) { pp t; t.d=0; t.id=i; for(int j=0; j<k; j++) if(s&(1<<j)) t.d+=p[j]; else t.d-=p[j]; pq[s].push(t); } } int ans=0; for(int s=0; s<=all; s++) { pp t1,t2; int t=all-s; while(!pq[s].empty()) { t1=pq[s].top(); if(!vis[t1.id]) break; pq[s].pop(); } while(!pq[t].empty()) { t2=pq[t].top(); if(!vis[t2.id]) break; pq[t].pop(); } if(!pq[s].empty()&&!pq[t].empty()) ans=max(ans,t1.d+t2.d); } printf("%d\n",ans); } } }
1004Mutiples on a circle
比赛的时候因为感觉数据连在一起将远远超出long long而不敢下手,后来想了想开了取余表来记录,但是却因为位数问题伤透了心,结果写的好长好长,时间效率也不是太好。。
勉强算A了。。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <string> #include <vector> #include <queue> #include <map> using namespace std; const int MAXN = 50010; int a[MAXN]; int end[MAXN]; int len[MAXN]; int b[2][220]; int getlen(int n) { int ret = 0; while(n) { ret++; n/=10; } return ret; } int Ten[10]; int main() { int n,k; while(scanf("%d%d",&n,&k) == 2) { for(int i = 1;i <= n;i++) { scanf("%d",&a[i]); len[i] = getlen(a[i]); } Ten[0] = 1; for(int i = 1;i < 5;i++) Ten[i] = Ten[i-1]*10%k; int now = 0; memset(b,0,sizeof(b)); b[now][a[1]%k] = 1; long long ans = 0; ans += b[now][0]; for(int i = 2;i <= n;i++) { memset(b[now^1],0,sizeof(b[now^1])); b[now^1][a[i]%k] = 1; for(int j = 0;j < k;j++) { if(b[now][j] == 0)continue; int ttt = j*Ten[len[i]]%k+a[i]; ttt%=k; b[now^1][ttt] += b[now][j]; } now^=1; ans += b[now][0]; } end[n] = a[n]%k; int tmp = len[n]; int SSSS = Ten[len[n]]; for(int i = n-1;i>= 1;i--) { end[i] = a[i]*SSSS%k + end[i+1]; end[i]%=k; tmp += len[i]; SSSS = SSSS*Ten[len[i]]%k; } tmp = len[1]; SSSS = Ten[len[1]]; int tt = a[1]%k; for(int i = 1;i < n;i++) { b[now][end[i]]--; for(int j = 0;j < k;j++) { int ppp = (j*SSSS%k+tt)%k; if(ppp == 0)ans += b[now][j]; } tt = tt*Ten[len[i+1]]+a[i+1]; tt%=k; tmp+=len[i+1]; SSSS = SSSS*Ten[len[i+1]]%k; } printf("%I64d\n",ans); } return 0; }
1006Backup Plan
暴搞的一道题,唯一的问题是当m > n时需要讨论第二数据的内容(因为按题意每个数据库只有前两个有用途)然后所有内容按逆序写就可以了。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <string> #include <vector> #include <queue> #include <map> using namespace std; #define maxn 2005 #define INF 0xfffffff int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { if(n>m) { for(int i=1; i<=m; i++) { cout<<i<<' '<<n; if(i==1) { for(int j=i+1; j<n; j++) cout<<' '<<j; } else { for(int j=i+1; j<n; j++) { cout<<' '<<j; } for(int j=1; j<i; j++) { cout<<' '<<j; } } cout<<endl; } } else if(n==m) { for(int i=1; i<=m; i++) { cout<<i; if(i==1) { for(int j=i+1; j<=n; j++) { cout<<' '<<j; } } else { for(int j=i+1; j<=n; j++) { cout<<' '<<j; } for(int j=1; j<i; j++) { cout<<' '<<j; } } cout<<endl; } } else { int num=1,tmp=n,flag=0; for(int i=1; i<=m; i++) { int s=i%n?i%n:n; cout<<s; if(num<=n-1) { cout<<' '<<tmp; flag=tmp; num++; if(num==n) { num=1; tmp--; if(tmp==0) { flag=1; tmp=n; } } } for(int j=1; j<=n; j++) { if(j!=s&&j!=flag) cout<<' '<<j; } cout<<endl; } } } return 0; }
除去这三道,1003和1005也是能做的,可惜思路不够宽扩,硬生生的悲剧了。。