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;
}

总体来讲,应该有能力得一个更高的分数,还要努力啊!

posted @ 2018-10-02 18:46  DukeLv  阅读(187)  评论(0编辑  收藏  举报