NOIP2014 总结
这届的题其实很简单,也很好拿分,我自己测了一下,还是过不了400.。。我菜爆了!!!
T1 生活大爆炸版石头剪刀布
大水题,直接模拟就行。
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<cstring> using namespace std; #define duke(i,a,n) for(int i = a;i <= n;i++) #define lv(i,a,n) for(int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) const int INF = 1 << 30; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } int n,l1,l2; int a1[1000]; int a2[1000]; int mp[10][10] = {{0,-1,1,1,-1},{1,0,-1,1,-1},{-1,1,0,-1,1},{-1,-1,1,0,1},{1,1,-1,-1,0}}; int main() { read(n);read(l1);read(l2); duke(i,1,l1) read(a1[i]); duke(i,1,l2) read(a2[i]); int k1 = 0,k2 = 0,ans1 = 0,ans2 = 0; /*duke(i,0,4) { duke(j,0,4) printf("%3d",mp[i][j]); puts(""); }*/ duke(i,1,n) { k1 ++; k2 ++; if(k1 == l1 + 1) k1 = 1; if(k2 == l2 + 1) k2 = 1; //printf("%d %d %d\n",a1[k1],a2[k2],mp[a1[k1]][a2[k2]]); if(mp[a1[k1]][a2[k2]] == 1) ans1 ++; else if(mp[a1[k1]][a2[k2]] == -1) ans2++; } printf("%d %d\n",ans1,ans2); return 0; }
T2 联合权值
我的树形dp只得了40分,凉凉。。。但是正解和我的差不了多少,就差了一些细节~~~gg
40代码:
#include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<vector> #include<cstring> using namespace std; #define duke(i,a,n) for(int i = a;i <= n;i++) #define lv(i,a,n) for(int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) const int INF = 1 << 30; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } struct node { int l,r,nxt; }a[200010]; int len = 0,lst[200010]; void add(int x,int y) { a[++len].l = x; a[len].r = y; a[len].nxt = lst[x]; lst[x] = len; } int n,w[200010],root = 1,max_dep = 0; int vis[200010],f[200010]; vector <int> dep[200010]; void dfs(int rt,int depth,int fa) { vis[rt] = 1; dep[depth].push_back(rt); f[rt] = fa; max_dep = max(max_dep,depth); for(int k = lst[rt];k;k = a[k].nxt) { int y = a[k].r; if(vis[y] == 0) dfs(y,depth + 1,rt); } } int main() { read(n); duke(i,1,n - 1) { int x,y; read(x);read(y); add(x,y);add(y,x); } duke(i,1,n) read(w[i]); dfs(root,0,0); int ans = 0,maxn = 0; duke(i,0,max_dep) { int l1 = dep[i].size(); if(i != 0) { duke(j,0,l1 - 1) { duke(k,j + 1,l1 - 1) { if(j != k && f[dep[i][j]] == f[dep[i][k]]) { // printf("%d %d\n",dep[i][j],dep[i][k]); ans += w[dep[i][j]] * w[dep[i][k]]; maxn = max(maxn,w[dep[i][j]] * w[dep[i][k]]); } } } } if(i <= max_dep - 2) { int l2 = dep[i + 2].size(); duke(j,0,l1 - 1) { duke(k,0,l2 - 1) { if(f[f[dep[i + 2][k]]] == dep[i][j]) { // printf("%d %d\n",dep[i][j],dep[i + 2][k]); ans += w[dep[i][j]] * w[dep[i + 2][k]]; maxn = max(maxn,w[dep[i][j]] * w[dep[i + 2][k]]); } } } } } printf("%d %d\n",maxn,(ans * 2) % 10007); return 0; } /* 5 2 1 2 3 3 4 3 5 3 2 5 3 4 */
AC代码:
// luogu-judger-enable-o2 #include<iostream> #include<cstdio> #include<cmath> using namespace std; #define duke(i,a,n) for(int i = a;i <= n;i++) #define lv(i,a,n) for(int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) const int INF = 1 << 30; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } struct node { int l,r,nxt; }a[400010]; int len = 0,lst[400010]; void add(int x,int y) { a[++len].l = x; a[len].r = y; a[len].nxt = lst[x]; lst[x] = len; } const int mod = 10007; int n,w[400010],root = 1,max_dep = 0; int vis[400010],ans1,ans2; int cnt = 0; void dfs(int u,int f,int g) { int maf = 0,mas = 0,sum = 0,squ = 0; for(int k = lst[u];k;k = a[k].nxt) { int y = a[k].r; if(y != f) { sum = (sum + w[y]) % mod; squ = (squ + w[y] * w[y] % mod) % mod; if(w[y] > maf) mas = maf,maf = w[y]; else if(w[y] > mas) mas = w[y]; dfs(y,u,f); } } ans1 = max(ans1,max(mas * maf,w[u] * w[g])); ans2 = (ans2 + (sum * sum % mod - squ + mod) % mod + w[u] * w[g] * 2 % mod) % mod; } int main() { read(n); duke(i,1,n - 1) { int x,y; read(x);read(y); add(x,y);add(y,x); } duke(i,1,n) read(w[i]); dfs(1,0,0); printf("%d %d\n",ans1,ans2); return 0; } /* 5 2 1 2 3 3 4 3 5 3 2 5 3 4 */
T3 飞扬的小鸟
裸dp很好想,但是我又不知道哪错了,只得了55分,后来直接用别人代码交的。
55代码:
#include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<vector> #include<cstring> using namespace std; #define duke(i,a,n) for(int i = a;i <= n;i++) #define lv(i,a,n) for(int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) const int INF = 1 << 30; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } int pl[10010],mi[10010],n,m,k; struct guan { int p,l,h; bool operator < (const guan &x) const { return p < x.p; } }a[10010]; int mp[10010],len = 0; int dp[10002][1002]; int main() { read(n);read(m);read(k); duke(i,1,n) { read(pl[i]);read(mi[i]); } duke(i,1,k) { read(a[i].p); read(a[i].l); read(a[i].h); mp[a[i].p] ++; } sort(a + 1,a + k + 1); duke(i,0,n) { duke(j,0,m) dp[i][j] = 99999999; } duke(i,1,m) { dp[0][i] = 0; } duke(i,1,n) { duke(j,1,m) { if(j + mi[i] <= m) if(dp[i - 1][j + mi[i]] >= 0) dp[i][j] = min(dp[i - 1][j + mi[i]],dp[i][j]); if(j != m) { for(int k = 1;j - k * pl[i] > 0;k++) { // cout<<dp[i][j]<<endl; if(dp[i - 1][j - k * pl[i]] >= 0) { dp[i][j] = min(dp[i][j],dp[i - 1][j - k * pl[i]] + k); /*if(dp[i][j] == dp[i - 1][j - k * pl[i]] + k) printf("dp[%d][%d] = dp[%d][%d] + %d = %d\n",i,j,i - 1,j - k * pl[i],k,dp[i][j]);*/ } } } else { duke(k,1,pl[i]) { if(dp[i - 1][j - k] >= 0) dp[i][j] = min(dp[i][j],dp[i - 1][j - k] + 1); } } } // printf("%d\n",dp[i][4]); if(mp[i] == 1) { int x = a[++len].l; int y = a[len].h; duke(j,0,x) dp[i][j] = -1; duke(j,y,m) dp[i][j] = -1; } int ok = 0; duke(j,1,m) { if(dp[i][j] != -1 && dp[i][j] != 99999999) { ok = 1; break; } } if(ok == 0) { printf("0\n"); printf("%d\n",len - 1); return 0; } /*cout<<i<<endl; duke(j,1,m) { printf("%d ",dp[i][j]); } puts("");*/ } int maxn = 99999999; duke(i,1,m) maxn = min(dp[n][i],maxn); printf("1\n"); printf("%d\n",maxn); return 0; }
不一样的55分代码:(A的点还不一样)
#include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<vector> #include<cstring> using namespace std; #define duke(i,a,n) for(int i = a;i <= n;i++) #define lv(i,a,n) for(int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) const int INF = 1 << 30; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } int pl[10010],mi[10010],n,m,k; struct guan { int p,l,h,id; bool operator < (const guan &x) const { return p < x.p; } }a[10010]; int mp[10010],len = 0; int dp[10002][1002]; int main() { // freopen("1941.in","r",stdin); read(n);read(m);read(k); duke(i,1,n) { read(pl[i]);read(mi[i]); } duke(i,1,k) { read(a[i].p); read(a[i].l); read(a[i].h); a[i].id = i; mp[a[i].p] ++; } sort(a + 1,a + k + 1); duke(i,0,n) { duke(j,0,m) dp[i][j] = 99999999; } duke(i,1,m) { dp[0][i] = 0; } duke(i,1,n) { duke(j,1,m) { if(j + mi[i] <= m) if(dp[i - 1][j + mi[i]] >= 0) dp[i][j] = min(dp[i - 1][j + mi[i]],dp[i][j]); if(j != m) { for(int k = 1;j - k * pl[i] > 0;k++) { // cout<<dp[i][j]<<endl; if(dp[i - 1][j - k * pl[i]] >= 0) { dp[i][j] = min(dp[i][j],dp[i - 1][j - k * pl[i]] + k); /*if(dp[i][j] == dp[i - 1][j - k * pl[i]] + k) printf("dp[%d][%d] = dp[%d][%d] + %d = %d\n",i,j,i - 1,j - k * pl[i],k,dp[i][j]);*/ } } } else { duke(k,1,m) { if(dp[i - 1][j - k] >= 0) dp[i][j] = min(dp[i][j],dp[i - 1][j - k] + k / pl[i] + 1); } } } // printf("%d\n",dp[i][4]); if(mp[i] == 1) { int x = a[++len].l; int y = a[len].h; duke(j,0,x) dp[i][j] = -1; duke(j,y,m) dp[i][j] = -1; } int ok = 0; duke(j,1,m) { if(dp[i][j] != -1 && dp[i][j] != 99999999) { ok = 1; break; } } if(ok == 0) { printf("0\n"); printf("%d\n",len - 1); return 0; } /*cout<<i<<endl; duke(j,1,m) { printf("%d ",dp[i][j]); } puts("");*/ } int maxn = 99999999; duke(i,1,m) maxn = min(dp[n][i],maxn); printf("1\n"); printf("%d\n",maxn); return 0; }
AC代码:(不是我的)
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=10000+10; const int maxm=2000+10; int n,m,p; int x[maxn],y[maxn]; //i位置,上升x[i],下降y[i] int low[maxn],high[maxn]; //i位置能通过的范围是low[i]-high[i] int f[maxn][maxm]; //到(i,j)的最少点击次数 bool e[maxn]; //e[i]表示i位置有没有管道 int main() { scanf("%d%d%d",&n,&m,&p); for(int i=1; i<=n; ++i) scanf("%d%d",&x[i],&y[i]); for(int i=1; i<=n; ++i) { low[i]=1; high[i]=m; } int a,b,c; for(int i=1; i<=p; ++i) { scanf("%d%d%d",&a,&b,&c); e[a]=1; low[a]=b+1; high[a]=c-1; } memset(f,0x3f,sizeof(f)); for(int i=1; i<=m; ++i) f[0][i]=0; for(int i=1; i<=n; ++i) { for(int j=x[i]+1; j<=m+x[i]; ++j) f[i][j]=min(f[i-1][j-x[i]]+1,f[i][j-x[i]]+1); for(int j=m+1; j<=m+x[i]; ++j) f[i][m]=min(f[i][m],f[i][j]); for(int j=1; j<=m-y[i]; ++j) f[i][j]=min(f[i][j],f[i-1][j+y[i]]); for(int j=1; j<low[i]; ++j) f[i][j]=f[0][0]; //不能通过(INF) for(int j=high[i]+1; j<=m; ++j) f[i][j]=f[0][0]; //不能通过(INF) } int ans=f[0][0]; for(int j=1;j<=m;++j) { ans=min(ans,f[n][j]); } if(ans<f[0][0]) printf("1\n%d\n",ans); else{ int i,j; for(i=n;i>=1;i--) { for(j=1;j<=m;++j) { if(f[i][j]<f[0][0]) break; } if(j<=m) break; } ans=0; for(int j=1;j<=i;++j) { if(e[j]) ans++; } printf("0\n%d\n",ans); } return 0; }
T4 无线网络发射器选址
水题没的说,就是细节有点多,一开始一直90.。。边界不好判断。
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<vector> #include<cstring> using namespace std; #define duke(i,a,n) for(int i = a;i <= n;i++) #define lv(i,a,n) for(int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) const int INF = 1 << 30; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } int mp[160][160],d,n; int main() { read(d); read(n); duke(i,1,n) { int k,x,y; read(x);read(y);read(k); mp[x][y] = k; } int ans = 0,maxn = 0,num = 0; duke(i,0,128) { duke(j,0,128) { ans = 0; duke(x,max(0,i - d),min(128,i + d)) { duke(y,max(0,j - d),min(128,j + d)) { ans += mp[x][y]; } } if(ans == maxn) num++; else if(ans > maxn) { maxn = ans; num = 1; } } } printf("%d %d\n",num,maxn); return 0; }
T5 寻找道路
就是一个搜索题就行了,关键在于反向建边,从汇点出发。
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<cstring> using namespace std; #define duke(i,a,n) for(int i = a;i <= n;i++) #define lv(i,a,n) for(int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) const int INF = 1 << 30; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } struct node { int l,r,nxt; }a[200010]; int lst[10010],len; void add(int x,int y) { a[++len].l = x; a[len].r = y; a[len].nxt = lst[x]; lst[x] = len; } int s,t,n,m; bool vis[10040],pan[10040]; int dis[10040]; queue <int> qu; void bfs() { qu.push(t); vis[t] = 1; while(!qu.empty()) { // cout<<"QAQ"<<endl; int now = qu.front(); qu.pop(); // cout<<now<<endl; for(int k = lst[now];k;k = a[k].nxt) { int y = a[k].r; // cout<<y<<endl; if(vis[y] != 1) vis[y] = 1,qu.push(y); } } } void bfs2() { qu.push(t); dis[t] = 0; while(!qu.empty()) { int now = qu.front(); qu.pop(); for(int k = lst[now];k;k = a[k].nxt) { int y = a[k].r; if(pan[y] == 1) { pan[y] = 0; dis[y] = dis[now] + 1; qu.push(y); } } } } int main() { read(n);read(m); duke(i,1,m) { int x,y; read(x);read(y); if(x == y) continue; add(y,x); } read(s);read(t); bfs(); memcpy(pan,vis,sizeof(vis)); duke(i,1,n) { if(vis[i] == 0) for(int k = lst[i];k;k = a[k].nxt) { int y = a[k].r; pan[y] = 0; } } bfs2(); if(dis[s] == 0) printf("-1\n"); else printf("%d\n",dis[s]); return 0; }
T6 解方程
说是秦久韶,但是就是一个边乘边模就行了。
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<cstring> using namespace std; #define duke(i,a,n) for(int i = a;i <= n;i++) #define lv(i,a,n) for(int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) const int INF = 1 << 30; const long long mod = 23456789; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0',x %= mod; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } ll a[15000]; int n,m,ans = 0,num[1600000]; bool cal(int k) { ll sum = 0; lv(i,n,1) { sum = ((sum + a[i]) * (ll)k) % mod; } sum = (sum + a[0]) % mod; if(sum == 0) return true; else return false; } int main() { // freopen("2312.in","r",stdin); read(n);read(m); duke(i,0,n) { read(a[i]); // printf("%d\n",a[i]); } duke(i,1,m) { if(cal(i) == true) { ans++; num[ans] = i; } } if(ans == 0) printf("0\n"); else { printf("%d\n",ans); duke(i,1,ans) printf("%d\n",num[i]); } return 0; }
总体来讲,应该有能力得一个更高的分数,还要努力啊!
只想找一个不会伤害我的人