2018校赛网络预选赛

A.
这里写图片描述
水题,set查重从小到大扫描即可。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<set>
using namespace std;
int main()
{
    int t,i,j,k,n,num[200005];
    cin>>t;
    while(t--){
        cin>>n;
        set<int>s;
        for(i=0;i<n;i++) {
            scanf("%d", &j);
            s.insert(j);
        }j=0;
        set<int>::iterator iter=s.begin();
        for(;iter!=s.end();iter++){
            if(*iter!=j){
                cout<<j<<endl;break;
            }
            j++;
        }
    }

    return 0;
}

B.
这里写图片描述

C.
这里写图片描述
大意就是给定一个字符串,求字符串中有多少个“bupt”子串,注意子串不需要连续,类似于最长公共子串的定义。
做法也有点类似于最长公共子串,按串中每一位进行dp。小心即可

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
using namespace std;
char a[1000666], b[5] = "bupt";
int f[1000666][6];//f[i][j]表示目标串的前i-1位与bupt的前j-1位匹配的可能数
int p = 1e9 + 7;
int main(){
    int t;
    cin>>t;
    while (t--){
        scanf("%s", a);
        //memset(f, 0, sizeof(f));直接memset会tle
        int n = strlen(a), m = 4;
        for (int i = 0; i <= n; i++)
            f[i][0] = 1;//只把有必要的部分进行memset即可
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= 4; j++){
                f[i][j] = f[i-1][j] % p;//每一位显然首先等于上一位的可能值
                if (a[i-1] == b[j-1])
                    f[i][j] = (f[i][j] + f[i-1][j-1]) % p;//如果这一位相等,那么就加
                //cout<<i<<' '<<j<<' '<<f[i][j]<<endl;
            }
        printf("%d\n", f[n][m]);
    }
}

更神奇的做法则不用dp,直接从前往后扫,类似于乘法原理,但是这里换成了加,大概就是每扫到一个需要的字母,就加上需要的字母前一位的字母的个数。具体可以体会一下:

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const long long P=1e9+7;
int T,len;
char s[1000100];
long long k1,k2,k3,ans;
int main()
{
    cin>>T;
    getchar();
    while (T--)
    {
        len=0;
        k1=k2=k3=ans=0;
        for (char ch=getchar();ch!='\n';ch=getchar()) s[++len]=ch;
        for (int i=1;i<=len;++i)
        {
            if (s[i]=='b') k1=(k1+1)%P;
            if (s[i]=='u') k2=(k2+k1)%P;//相当于当前的u前面对应的b的个数
            //决定了当前位置的u有多少种bu的可能
            if (s[i]=='p') k3=(k3+k2)%P;
            if (s[i]=='t') ans=(ans+k3)%P;
        }
        cout<<ans<<endl;
    }
    return 0;
}

D.
没有截图。题目大意是有很多堆石子,然后每一堆里面有若干石子,两个人玩游戏,每次可以选中一堆取石子,每次至少取一个石子,最多可以把整堆取走,每轮会给定一个游戏区间,也就是这轮游戏在第l~r堆石子上进行(这轮结束以后石子归位),每轮都是甲先手,然后甲赢的话f就是1,否则为0.
有多组test,对于每一组test,输出 fi*2^(m-i) 之和,m是每个test的游戏轮数,n为石子个数。

这是个经典的nim游戏,但是由于每轮游戏要进行n轮,所以为了高效,可以考虑弄个类似于前缀和那样的前缀xor数组,然后因为同一个数xor两次相当于抵消,所以可以高效求出。后面的幂方则可以搞一个快速幂。

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e6+5;
const int mod=1e9+7;
typedef long long ll;
ll num[N],xorr[N];
ll mod_pow(ll x, ll n, ll mod)
{
    ll res = 1;
    while (n) {
        if (n & 1)
            res = res*x%mod;
        x = x*x%mod;
        n >>= 1;
    }
    return res;
}
int main()
{
    int t,i,j,n,m;
    cin>>t;
    while(t--){
        ll ans=0;
        cin>>n>>m;
        for(i=1;i<=n;i++){scanf("%d",&num[i]);}
        xorr[1]=num[1];//特判1的情况
        for(i=2;i<=n;i++)xorr[i]=num[i]^xorr[i-1];
        for(i=1;i<=m;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            if(a>1)
                j=xorr[b]^xorr[a-1];//抵消前缀亦或
            else
                j=xorr[b];//l为1不用抵消
            int f;
            if(j){
                f=1;
            }
            else f=0;
            ans=(ans+mod_pow(2,m-i,mod)*f)%mod;
        }
        cout<<ans<<endl;
    }

    return 0;
}

E.
这里写图片描述

F.
这里写图片描述
大意就是给定一棵树,给定所有节点之间的距离(相邻的节点),每个节点都有自己的权值,然后求一个点使得 (所有其他点的权值*到这个点的距离) 的总和最小。注意,没有说明是二叉树。
题目做法有点类似于POJ3585,首先进行一次扫描,然后换根不停地转移,然后记录整个过程中的最小值并输出即可。
在第一次扫描的时候任选一个节点为根(比如1),然后扫描过程中处理处每个点的子节点的权值之和与(子节点的权值*路径长度)之和,保存在节点里,二次扫描换根的时候就会简单很多。
二次扫描的时候,则用预处理的值高效计算转移结果。
扫描换根如图所示这里写图片描述

代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <vector>
using namespace std;
int n;
typedef long long ll;
struct data{
    int y;
    ll w;
};
vector<data> g[500055];
ll sum[500055];//每个节点的子节点的(权值*路径)和
ll cnt[500055];//每个节点的子节点权值和(包括节点本身的权值)
ll w[500055];//记录每个点的权值
//ll ans[500055];
ll emmm;//用于存储答案
void dfs(int x, int fa){//第一次扫描
    cnt[x] = w[x];
    sum[x] = 0;//cout<<x<<' '<<cnt[x]<<endl;
    for (int i = 0; i < g[x].size(); i++){
        int y = g[x][i].y;
        ll W = g[x][i].w;
        if (y == fa)
            continue;
        dfs(y, x);
        cnt[x] += cnt[y];
        sum[x] += cnt[y] * W + sum[y];
    }

}
void dfs1(int x, int fa){//换根扫描
    for (int i = 0; i < g[x].size(); i++){
        int y = g[x][i].y;
        ll W = g[x][i].w;
        if (y == fa)
            continue;
        sum[y] = sum [y] + sum[x] - sum[y] - cnt[y] * W + (cnt[x] - cnt[y]) * W;
        cnt[y] += cnt[x] - cnt[y];
        emmm = min(emmm, sum[y]);
        //cout<<sum[y]<<endl;
        dfs1(y, x);
    }
}
int main(){
    //cout<<ans;
    cin>>n;
    for (int i = 1; i < n; i++){
        int x, y; ll w;
        scanf("%d%d%lld", &x, &y, &w);
        g[x].push_back((data){y, w});
        g[y].push_back((data){x, w});
    }
    for (int i = 1; i <= n; i++)
        scanf("%lld", &w[i]);
    dfs(1, -1);
    emmm = sum[1];
    //cout<<emmm<<endl;
    dfs1(1, 0);
    cout<<emmm;
    return 0;
}

G.
这里写图片描述

大意就是给定一个坐标轴,轴上有若干个点,每个点有权值,求坐标轴上的一个点使得其他所有点的(权值*到这个点的距离)总和最小。
这其实是一个带权中位数的问题,三分也能过比赛数据…
带权中位数:https://blog.csdn.net/Clove_unique/article/details/50618784
这里写图片描述

代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef unsigned long long ll;
struct data{
    int x;//坐标
    ll q;//权值
}a[100011];
bool cmp(data A, data B){
    return A.x < B.x;
}
ll f(ll x, int t){
    if (t == 1)
        return x;
    if (t == 2)
        return x * x;
    if (t == 3)
        return x * x * x;
    return x * x * x * x;
}
int main(){
    int T;
    cin>>T;
    while (T--){
        int n, t;
        cin>>n>>t;
        ll sum = 0;
        for (int i = 1; i <= n; i++){
            scanf("%lld%lld", &a[i].q, &a[i].x);
            a[i].q = f(a[i].q, t);//预处理权值
            sum += a[i].q;
        }
        sort(a + 1, a + 1 + n, cmp);
        ll tmp = 0;
        int i;
        for (i = 1; i <= n; i++){
            tmp += a[i].q;
            if (tmp * 2 > sum)
                break;
        }
        ll ans = 0;
        for (int j = 1; j <= n; j++)
            ans += abs(a[j].x - a[i].x) * a[j].q;
        cout<<ans<<'\n';
    }
    return 0;
}

三分做法:

#include <bits/stdc++.h>
using namespace std;

const long long INF=9223372036854775807ll;
const int N=100005;

int n,t;
int q[N],x[N];

inline int read()
{
    int a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}

int pow(int x,int y)
{
    int ans=1;
    for (int i=1;i<=y;i++)
        ans*=x;
    return ans;
}

long long calc(int mid)
{
    long long ans=0;
    for (int i=1;i<=n;i++)
        ans+=(long long)abs(mid-x[i])*q[i];
    return ans;
}

int main()
{
    int testcase=read();
    while (testcase--)
    {
        n=read(); t=read();
        int L=1000000,R=0;
        for (int i=1;i<=n;i++)
            q[i]=pow(read(),t),x[i]=read(),L=min(L,x[i]),R=max(R,x[i]);
        while (R-L>5)
        {
            int lmid=(L+L+R)/3;
            int rmid=(L+R+R)/3;
            if (calc(lmid)<calc(rmid)) R=rmid;
            else L=lmid;
        }
        long long ans=INF;
        for (int i=L;i<=R;i++)
            ans=min(ans,calc(i));
        cout << ans << endl;
    }
    return 0;
}

H.
这里写图片描述

超级暴力的bfs爆搜:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <istream>
#define forr(a,b,c) for(int a=b;a<=c;a++)
#define MAX(a,b) (a>b)?a:b;
#define MIN(a,b) (a<b)?a:b;
#define memsett(a) memset(a,0,sizeof(a));
using namespace std;
char mapp[2002][2002];
bool ismap[2002][2002];
int loca[2][10000][2];
int a,b,final,finded;
bool boo;
int find(int x,int y){
    if (ismap[x][y]==true) return 0;
    else if (mapp[x][y]=='.'||mapp[x][y]=='T') return x*10000+y;
    else if (mapp[x][y]=='U'){
        ismap[x][y]=true;
        x=x-1;
        while(mapp[x][y]=='.')x=x-1;
        if (mapp[x][y]=='#')x=x+1;
        return find(x,y);
    }
    else if (mapp[x][y]=='D'){
        ismap[x][y]=true;
        x=x+1;
        while(mapp[x][y]=='.')x=x+1;
        if (mapp[x][y]=='#')x=x-1;
        return find(x,y);
    }
    else if (mapp[x][y]=='L'){
        ismap[x][y]=true;
        y=y-1;
        while(mapp[x][y]=='.')y=y-1;
        if (mapp[x][y]=='#')y=y+1;
        return find(x,y);
    }
    else if (mapp[x][y]=='R'){
        ismap[x][y]=true;
        y=y+1;
        while(mapp[x][y]=='.')y=y+1;
        if (mapp[x][y]=='#')y=y-1;
        return find(x,y);
    }
    return 0;
}
int main(){
    do{

        memsett(mapp);
        memsett(ismap);
        memsett(loca);
        //初始化
        loca[0][0][1]=1;
        //loca[0][0][0]表示步数;loca[0][0][1]表示个数;

        cin>>a>>b;
        if(a==0&&b==0)return 0;
        forr(i,0,b+1){
            mapp[0][i]='#';
            mapp[a+1][i]='#';
        }
        forr(i,0,a+1){
            mapp[i][0]='#';
            mapp[i][b+1]='#';
        }
        getchar();
        forr(i,1,a){
            forr(j,1,b){
                cin>>mapp[i][j];
                if (mapp[i][j]=='S'){
                    loca[0][1][0]=i;
                    loca[0][1][1]=j;
                    ismap[i][j]=true;
                }
                if (mapp[i][j]=='T'){
                    final=i*10000+j;
                }
            }
            getchar();
        }
        //读入
        boo=false;
        do {
            loca[0][0][0]++;
            loca[loca[0][0][0] % 2][0][1] = 0;
            forr(i, 1, loca[(loca[0][0][0] + 1) % 2][0][1]) {
                finded = find(loca[(loca[0][0][0] + 1) % 2][i][0] + 1, loca[(loca[0][0][0] + 1) % 2][i][1]);
                if (finded == final) {
                    boo = true;
                    break;
                }
                if (finded != 0) {
                    loca[loca[0][0][0] % 2][0][1]++;
                    loca[loca[0][0][0] % 2][loca[loca[0][0][0] % 2][0][1]][0] = finded / 10000;
                    loca[loca[0][0][0] % 2][loca[loca[0][0][0] % 2][0][1]][1] = finded % 10000;
                    ismap[finded / 10000][finded % 10000] = true;
                }
                finded = find(loca[(loca[0][0][0] + 1) % 2][i][0] - 1, loca[(loca[0][0][0] + 1) % 2][i][1]);
                if (finded == final) {
                    boo = true;
                    break;
                }
                if (finded != 0) {
                    loca[loca[0][0][0] % 2][0][1]++;
                    loca[loca[0][0][0] % 2][loca[loca[0][0][0] % 2][0][1]][0] = finded / 10000;
                    loca[loca[0][0][0] % 2][loca[loca[0][0][0] % 2][0][1]][1] = finded % 10000;
                    ismap[finded / 10000][finded % 10000] = true;
                }
                finded = find(loca[(loca[0][0][0] + 1) % 2][i][0], loca[(loca[0][0][0] + 1) % 2][i][1] + 1);
                if (finded == final) {
                    boo = true;
                    break;
                }
                if (finded != 0) {
                    loca[loca[0][0][0] % 2][0][1]++;
                    loca[loca[0][0][0] % 2][loca[loca[0][0][0] % 2][0][1]][0] = finded / 10000;
                    loca[loca[0][0][0] % 2][loca[loca[0][0][0] % 2][0][1]][1] = finded % 10000;
                    ismap[finded / 10000][finded % 10000] = true;
                }
                finded = find(loca[(loca[0][0][0] + 1) % 2][i][0], loca[(loca[0][0][0] + 1) % 2][i][1] - 1);
                if (finded == final) {
                    boo = true;
                    break;
                }
                if (finded != 0) {
                    loca[loca[0][0][0] % 2][0][1]++;
                    loca[loca[0][0][0] % 2][loca[loca[0][0][0] % 2][0][1]][0] = finded / 10000;
                    loca[loca[0][0][0] % 2][loca[loca[0][0][0] % 2][0][1]][1] = finded % 10000;
                    ismap[finded / 10000][finded % 10000] = true;
                }
            }
            if (boo) {
                cout << loca[0][0][0] << endl;
                break;
            }
            if (loca[loca[0][0][0] % 2][0][1] == 0) {
                cout << -1 << endl;
                break;
            }
        }while(true);
    }while(1);
}

同样暴力的dijkstra:

#include <bits/stdc++.h>
using namespace std;

typedef pair<int,int> pa;

const int N=4000005;
const int INF=0x3f3f3f3f;
const int dx[4]={0,0,1,-1};
const int dy[4]={1,-1,0,0};

int n,m,cnt,S,T;
char str[2005][2005];
int head[N],dis[N];
int Next[N<<2],List[N<<2],key[N<<2];
bool vis[N];

inline int read()
{
    int a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}

inline void insert(int x,int y,int z)
{
    Next[++cnt]=head[x];
    head[x]=cnt;
    List[cnt]=y;
    key[cnt]=z;
}

inline int id(int x,int y)
{
    return (x-1)*m+y;
}

inline bool judge(int x,int y)
{
    if (x<1||x>n||y<1||y>m||str[x][y]=='#') return false;
    return true;
}

inline int dijkstra(int S,int T)
{
    priority_queue<pa,vector<pa>,greater<pa> > q;
    memset(dis,0x3f,sizeof(dis));
    memset(vis,false,sizeof(vis));
    q.push(make_pair(0,S));
    dis[S]=0;
    while (!q.empty())
    {
        int x=q.top().second; q.pop();
        if (vis[x]) continue; vis[x]=true;
        for (int i=head[x];i;i=Next[i])
            if (dis[List[i]]>dis[x]+key[i])
            {
                dis[List[i]]=dis[x]+key[i];
                q.push(make_pair(dis[List[i]],List[i]));
            }
    }
    return dis[T]==INF?-1:dis[T];
}

int main()
{
    n=read(); m=read();
    while (n||m)
    {
        cnt=0;
        memset(head,0,sizeof(head));
        for (int i=1;i<=n;i++)
            scanf("%s",str[i]+1);
        for (int i=0;i<=m+1;i++)
            str[0][i]=str[n+1][i]='#';
        for (int i=0;i<=n+1;i++)
            str[i][0]=str[i][m+1]='#';
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++)
            {
                if (str[i][j]=='#') continue;
                if (str[i][j]=='.'||str[i][j]=='S')
                    for (int k=0;k<4;k++)
                    {
                        int nx=i+dx[k],ny=j+dy[k];
                        if (judge(nx,ny))
                            insert(id(i,j),id(nx,ny),1);
                    }
                if (str[i][j]=='S') S=id(i,j);
                if (str[i][j]=='T') T=id(i,j);
            }
        for (int i=1;i<=n;i++)
        {
            int now=-1;
            for (int j=0;j<=m;j++)
            {
                if (str[i][j]=='L')
                {
                    if (now==-1) continue;
                    insert(id(i,j),id(i,now),0);
                }
                if (str[i][j]=='#') now=j+1;
                else if (str[i][j]!='.'&&str[i][j]!='S') now=j;
            }
            now=-1;
            for (int j=m+1;j;j--)
            {
                if (str[i][j]=='R')
                {
                    if (now==-1) continue;
                    insert(id(i,j),id(i,now),0);
                }
                if (str[i][j]=='#') now=j-1;
                else if (str[i][j]!='.'&&str[i][j]!='S') now=j;
            }
        }
        for (int i=1;i<=m;i++)
        {
            int now=-1;
            for (int j=0;j<=n;j++)
            {
                if (str[j][i]=='U')
                {
                    if (now==-1) continue;
                    insert(id(j,i),id(now,i),0);
                }
                if (str[j][i]=='#') now=j+1;
                else if (str[j][i]!='.'&&str[j][i]!='S') now=j;
            }
            now=-1;
            for (int j=n+1;j;j--)
            {
                if (str[j][i]=='D')
                {
                    if (now==-1) continue;
                    insert(id(j,i),id(now,i),0);
                }
                if (str[j][i]=='#') now=j-1;
                else if (str[j][i]!='.'&&str[j][i]!='S') now=j;
            }
        }
        cout<<dijkstra(S,T)<<endl;
        n=read(); m=read();
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
项目:使用 JavaScript 编写的杀死幽灵游戏(附源代码) 杀死鬼魂游戏是使用 Vanilla JavaScript、CSS 和 HTML 画布开发的简单项目。这款游戏很有趣。玩家必须触摸/杀死游荡的鬼魂才能得分。您必须将鼠标悬停在鬼魂上 - 尽量得分。鬼魂在眨眼间不断从一个地方移动到另一个地方。您必须在 1 分钟内尽可能多地杀死鬼魂。 游戏制作 这个游戏项目只是用 HTML 画布、CSS 和 JavaScript 编写的。说到这个游戏的特点,用户必须触摸/杀死游荡的幽灵才能得分。游戏会根据你杀死的幽灵数量来记录你的总分。你必须将鼠标悬停在幽灵上——尽量得分。你必须在 1 分钟内尽可能多地杀死幽灵。游戏还会显示最高排名分数,如果你成功击败它,该分数会在游戏结束屏幕上更新。 该游戏包含大量的 javascript 以确保游戏正常运行。 如何运行该项目? 要运行此游戏,您不需要任何类型的本地服务器,但需要浏览器。我们建议您使用现代浏览器,如 Google Chrome 和 Mozilla Firefox。要玩游戏,首先,单击 index.html 文件在浏览器中打开游戏。 演示: 该项目为国外大神项目,可以作为毕业设计的项目,也可以作为大作业项目,不用担心代码重复,设计重复等,如果需要对项目进行修改,需要具备一定基础知识。 注意:如果装有360等杀毒软件,可能会出现误报的情况,源码本身并无病毒,使用源码时可以关闭360,或者添加信任。
javascript 中的 Paint War Game 是使用 HTML、CSS 和 JavaScript 开发的。谈到游戏玩法,这款游戏的主要目标是建造比敌人更多的油漆砖。您所要做的就是使用 WASD 键输入玩家的动作。您可以使用 VS Code 来运行该项目。 关于项目 每次您的玩家走过一块瓷砖时,它都会被涂成您的团队颜色。您必须在同一块瓷砖上走 4 次才能获得更多游戏点数。瓷砖会被您的团队挡住,并且不能再被偷走。如果您走过另一支球队的瓷砖,它会像您第一次走过时一样被涂上颜色。如果您创建一个封闭的被阻挡瓷砖图形,图形内所有未被阻挡的瓷砖都将固定为您的团队颜色。这个游戏充满乐趣,创造和重新即兴发挥会更有趣。 要运行此项目,我们建议您使用现代浏览器,例如 Google Chrome、  Mozilla Firefox。该游戏可能还支持 Explorer/Microsoft Edge。 演示: javascript 中的 Paint War Game 是使用 HTML、CSS 和 JavaScript 开发的。谈到游戏玩法,这款游戏的主要目标是建造比敌人更多的油漆砖。您所要做的就是使用 WASD 键输入玩家的动作。您可以使用 VS Code 来运行该项目。 关于项目 每次您的玩家走过一块瓷砖时,它都会被涂成您的团队颜色。您必须在同一块瓷砖上走 4 次才能获得更多游戏点数。瓷砖会被您的团队挡住,并且不能再被偷走。如果您走过另一支球队的瓷砖,它会像您第一次走过时一样被涂上颜色。如果您创建一个封闭的被阻挡瓷砖图形,图形内所有未被阻挡的瓷砖都将固定为您的团队颜色。这个游戏充满乐趣,创造和重新即兴发挥会更有趣。 要运行此项目,我们建议您使用现代浏览器,例如 Google Chrome、  Mozilla Firefox。该游戏可能还支持 Explorer/Microsoft Edge。 演示: 该项目为国外大神项目,可以作为毕业设计的项目,也可以作为大作业项目,不用担心代码重复,设计重复等,如果需要对项目进行修改,需要具备一定基础知识。 注意:如果装有360等杀毒软件,可能会出现误报的情况,源码本身并无病毒,使用源码时可以关闭360,或者添加信任。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值