NENU ACM 13级训练赛 2014-11-29(Ural Regional School Programming Contest 2014)

2014年乌拉尔校赛,题很新,也是蛮有质量的,建议把题全做完。


部分题解from KILLBILL's source code~


A题:组合数求一下就可以了,注意k的值有坑。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
const int M=1e5+10;
char a[M];
int num[32];
int C[32][32];
int main(){
    for(int i=0;i<32;i++){
        C[i][i]=1;
        C[i][0]=1;
    }
    for(int i=1;i<32;i++){
        for(int j=1;j<i;j++){
            C[i][j]=C[i-1][j]+C[i-1][j-1];
        }
    }
    int k;
    while(~scanf("%s%d",a,&k)){
        mt(num,0);
        for(int i=0;a[i];i++){
            num[a[i]-'a']++;
        }
        sort(num,num+26);
        int sum=0;
        int kk=0;
        for(int i=25;i>=0;i--){
            sum+=num[i];
            kk++;
            if(kk==k) break;
        }
        printf("%d ",sum);
        if(k==26){
            puts("1");
            continue;
        }
        if(num[26-k]==0){
            puts("1");
            continue;
        }
        if(num[26-k-1]!=num[26-k]){
            puts("1");
            continue;
        }
        int cn=0,cm=0;
        for(int i=0;i<26;i++){
            if(num[i]==num[26-k]){
                cn++;
            }
        }
        for(int i=26-k;i<26;i++){
            if(num[i]==num[26-k]){
                cm++;
            }
        }
        printf("%d\n",C[cn][cm]);
    }
    return 0;
}


B题:水题,模拟一下。

#include<cstdio>
int main(){
    int t,n,k,ans;
    while(~scanf("%d",&t)){
        while(t--){
            scanf("%d%d",&n,&k);
            int x=n/k;
            int y=n%k;
            ans=y*(x+1)*(n-x-1)+(k-y)*x*(n-x);
            printf("%d\n",ans/2);
        }
    }
    return 0;
}


C题:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define INF 0x3f3f3f3f
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;

char s[400000];
bool CanChange[400000];
int used[1000];

void output(){
    for(int i=0;s[i];i++){
        if(s[i] != '?')continue;
        CanChange[i] = true;
        if(i%2 == 0){
            s[i] = 'z';
        }else{
            s[i] = 'a';
        }
    }
}

int main(){
    int k;
    while(scanf("%s",s)!=EOF){
        scanf("%d",&k);
        memset(CanChange,0,sizeof CanChange);
        memset(used,0,sizeof used);
        output();
        for(int i=0; s[i]; i++){
            used[s[i]]++;
        }
        int cnt = 0;
        for(int i='a'; i<='z'; i++){
            if(!used[i])continue;
            cnt++;
        }
        if(cnt>=k){
            puts(s);
            continue;
        }
        bool ok = true;
        k -= cnt;
        while(k--){
            int who,pos;
            int dt = -INF;
            for(int i='a'; i<='z' ;i++){
                if(used[i])continue;
                for(int j=0; s[j]; j++){
                    if(CanChange[j] == 0)continue;
                    char now = s[j];
                    if(used[now] == 1)continue;
                    int getbefore,getnow;
                    if(j%2 == 0){
                        getbefore = now;
                        getnow = i;
                    }else{
                        getbefore = -now;
                        getnow = -i;
                    }

                    if(getnow-getbefore>dt){
                        dt = getnow-getbefore;
                        who = i;
                        pos = j;

                    }
                }
            }
            if(dt == -INF){
                ok=false;
                break;
            }
            used[s[pos]] --;
            used[who] = 1;
            s[pos] = who;
            CanChange[pos] = false;
        }

        if(!ok){
            puts("-1");
        }else{
            puts(s);
        }
    }
    return 0;
}


D题:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define INF 0x3f3f3f3f
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;

const int maxn = 1000;
char mp[maxn][maxn];

int nextx[]={-1,0,1,0}; // shunshizheng up,right,down,left;
int nexty[]={0,1,0,-1};
int n,m;

bool isOver(int x,int y){
    if(x<0||y<0||x>=n||y>=m){
        return true;
    }
    return false;
}

int val[1000];
int number;
int nownum;
int num[1000000];

int getval(){
    if(number == nownum){
        return num[nownum-1];
    }
    return num[nownum++];
}


int main(){

    while(scanf("%d%d",&n,&m)!=EOF){
        for(int i=0;i<n;i++){
            scanf("%s",mp[i]);
        }
        scanf("%d",&number);
        for(int i=0;i<number;i++){
            scanf("%d",&num[i]);
        }
        int stp = 0;
        nownum = 0;
        int x = 0,y = 0;
        int nowdir = 1;
        int nowval = 0;
        memset(val,0,sizeof val);

        while(1){
            if(mp[x][y] == '^'){
                nowdir = 0;
            }else if(mp[x][y] == '>'){
                nowdir = 1;
            }else if(mp[x][y] == 'v'){
                nowdir = 2;
            }else if(mp[x][y] == '<'){
                nowdir = 3;
            }else if(mp[x][y] == '+'){
                nowval++;
            }else if(mp[x][y] == '-'){
                nowval--;
            }else if(mp[x][y] == '.'){

            }else if(mp[x][y] == '?'){
                nowval = getval();
            }else if(mp[x][y] == '!'){
                printf("%d\n",nowval);
                nowval = 0;
            }else if(mp[x][y] == '@'){
                if(nowval == 0){
                    nowdir --;
                    if(nowdir == -1)nowdir = 3;
                }else{
                    nowdir ++;
                    if(nowdir == 4)nowdir = 0;
                }
            }else if(mp[x][y]>='A' && mp[x][y]<='Z'){
                swap(val[mp[x][y]],nowval);
            }else if(mp[x][y] == '#'){
                break;
            }

            if(abs(nowval)>100000){
                puts("OVERFLOW ERROR");
                break;
            }

            x = x+nextx[nowdir];
            y = y+nexty[nowdir];

            if(isOver(x,y)){
                puts("RUNTIME ERROR");
                break;
            }

            stp++;
            if(stp >= 1000000){
                puts("TIME LIMIT EXCEEDED");
                break;
            }

        }
    }
    return 0;
}


E题:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define INF 0x3f3f3f3f
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;

char ch[110][110] =
{
    "?.B?Av....A.AB<.",
    ".....>.?v>v..>.v",
    ".....>..>@...A..",
    ".....-...A>B-@..",
    ".....^A.+<...>^.",
    "v........A.....<",
    ">C+CA--v........",
    "^.....A@C!#....."
};

int main()
{
    puts("8 16");
    for(int i = 0; i < 8; i ++)
        puts(ch[i]);
}


F题:汉诺塔的变形,知道汉诺塔的步数公式2^n-1,然后推一推就可以出来了。

#include<cstdio>
typedef long long LL;
const int M=55;
char a[M];
LL p[M];
int main(){
    p[0]=1;
    for(int i=1;i<M;i++){
        p[i]=p[i-1]*2;
    }
    int n;
    while(~scanf("%d%s",&n,a)){
        LL ans=0;
        int id=0;
        for(int i=n;i>=1;i--){
            int his=a[i-1]-'A';
            if(his==id) continue;
            ans+=p[i-1];
            id=0^1^2^id^his;
        }
        printf("%lld\n",ans);
    }
    return 0;
}


G题:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define INF 0x3f3f3f3f
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;

const int MID = 330;
const int maxn = 100100;
const int MOD = 1000000007;

vector<int> G[maxn];
vector<int> up[maxn];
int add[maxn], val[maxn];

int query(int v)
{
    int ret = val[v];
    for(int i = 0; i < up[v].size(); i ++)
    {
        int u = up[v][i];
        ret = (ret + add[u]) % MOD;
    }
    return ret;
}

void update(int v, int ad)
{
    if(G[v].size() <= MID)
    {
        for(int i = 0; i < G[v].size(); i ++)
        {
            int u = G[v][i];
            val[u] = (val[u] + ad) % MOD;
        }
    }
    else
    {
        add[v] = (add[v] + ad) % MOD;
    }
}

int main()
{
    int n;
    while(scanf("%d", &n) != EOF)
    {
        for(int i = 1; i <= n; i ++)
        {
            scanf("%d", &val[i]);
            G[i].clear(), up[i].clear();
            add[i] = 0;
        }
        for(int i = 1; i < n; i ++)
        {
            int u, v; scanf("%d%d", &u, &v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        for(int i = 1; i <= n; i ++)
        {
            for(int j = 0; j < G[i].size(); j ++)
            {
                int v = G[i][j];
                if(G[v].size() > MID) up[i].push_back(v);
            }
        }
        int m; scanf("%d", &m);
        while(m --)
        {
//            puts("----------");
            int op, v;
            scanf("%d%d", &op, &v);
            if(op == 1)
            {
                int ans = query(v);
                update(v, ans);
            }
            else
            {
                int ans = query(v);
                printf("%d\n", ans);
            }
        }
    }
}


H题:看到图就能过了

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define INF 0x3f3f3f3f
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;

int main()
{
    char ans[10][10] = {"11", "01", "60", "80"};
    int n;
    while(scanf("%d", &n) != EOF)
    {
        if(n > 4) puts("Glupenky Pierre");
        else
        {
            for(int i = 0; i < n; i ++)
            {
                printf("%s%c", ans[i], i == n - 1? '\n' : ' ');
            }
        }
    }
}


I题:给a、b、c三条边,问能不能搞成三角形,且定点都是在整数格点上。

        定一个顶点在原点,然后以两条边做圆,答案一定出现在圆上的整数格点上。

        那么问题就转化为了在两个圆上分别找合法的点。

        没有好方法,那就暴力找吧,当然,只要找1/4圆就可以了。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define INF 0x3f3f3f3f
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;

struct Point
{
    int x, y;
    Point(int x = 0, int y = 0)
        :x(x), y(y){}
    void out()
    {
        printf("%d %d\n", x, y);
    }
};

vector<Point> v;

LL sqr(int x)
{
    return 1ll * x * x;
}

LL dist(Point a, Point b)
{
    return sqr(a.x - b.x) + sqr(a.y - b.y);
}

int main()
{
    int a, b, c;
    while(scanf("%d%d%d", &a, &b, &c) != EOF)
    {
        Point p1(0, 0);
        v.clear();
        for(int i = 0; i <= a; i ++)
        {
            LL l = 1ll * a * a - 1ll * i * i;
            int q = sqrt(l + 0.0);
            if(1ll * q * q != l) q ++;
            if(1ll * q * q != l) continue;
            v.push_back(Point(i, q));
        }
        for(int i = 0; i <= b; i ++)
        {
            LL l = 1ll * b * b - 1ll * i * i;
            int q = sqrt(l + 0.0);
            if(1ll * q * q != l) q ++;
            if(1ll * q * q != l) continue;
            Point tmp = Point(i, q);
            for(int j = 0; j < v.size(); j ++)
            {
                LL l = dist(v[j], tmp);
                if(l != 1ll * c * c) continue;
                int q = sqrt(l + 0.0);
                if(1ll * q * q != l) q ++;
                if(1ll * q * q != l) continue;
                p1.out();
                tmp.out();
                v[j].out();
                return 0;
            }
            tmp = Point(-i, -q);
            for(int j = 0; j < v.size(); j ++)
            {
                LL l = dist(v[j], tmp);
                if(l != 1ll * c * c) continue;
                int q = sqrt(l + 0.0);
                if(1ll * q * q != l) q ++;
                if(1ll * q * q != l) continue;
                p1.out();
                tmp.out();
                v[j].out();
                return 0;
            }
            tmp = Point(-i, q);
            for(int j = 0; j < v.size(); j ++)
            {
                LL l = dist(v[j], tmp);
                if(l != 1ll * c * c) continue;
                int q = sqrt(l + 0.0);
                if(1ll * q * q != l) q ++;
                if(1ll * q * q != l) continue;
                p1.out();
                tmp.out();
                v[j].out();
                return 0;
            }
            tmp = Point(i, -q);
            for(int j = 0; j < v.size(); j ++)
            {
                LL l = dist(v[j], tmp);
                if(l != 1ll * c * c) continue;
//                cout << l  << " " << dist(v[j], tmp) << endl;
                int q = sqrt(l + 0.0);
                if(1ll * q * q != l) q ++;
                if(1ll * q * q != l) continue;
                p1.out();
                tmp.out();
                v[j].out();
                return 0;
            }
        }
        puts("-1");
    }
}


J题:统计一下手机的型号就可以了

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define INF 0x3f3f3f3f
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;
struct in{
    string name;
    int num,cost;
    bool friend operator<(const in &a,const in &b){
        if(a.num==b.num) return a.cost<b.cost;
        return a.num>b.num;
    }
}p[8];
int main(){
    map<string,int> mp;
    int e=0;
    for(int i=0;i<6;i++){
        string tmp;
        cin>>tmp;
        cin>>tmp;
        int co;
        scanf("%d",&co);
        if(mp.find(tmp)==mp.end()){
            mp[tmp]=e;
            p[e].name=tmp;
            p[e].num=0;
            p[e].cost=0x3f3f3f3f;
            e++;
        }
        int id=mp[tmp];
        p[id].num++;
        p[id].cost=min(p[id].cost,co);
    }
    sort(p,p+e);
    cout<<p[0].name<<endl;
}


K题:图论,两遍BFS

#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
const int M=1e5+10;
vector<int> g[M];
bool vis[M];
void bfs(int s,int d[]) {
    mt(vis,0);
    vis[s]=true;
    queue<int> q;
    while(!q.empty()) q.pop();
    q.push(s);
    while(!q.empty()) {
        int u=q.front();
        q.pop();
        int len=g[u].size();
        for(int i=0; i<len; i++) {
            int v=g[u][i];
            if(!vis[v]) {
                vis[v]=true;
                d[v]=d[u]+1;
                q.push(v);
            }
        }
    }
}
int sd[M],rd[M],d[M],ans;
struct Q {
    int step,val,id;
} now,pre;
queue<Q> q;
void solve(int s,int f) {
    ans=0;
    mt(d,0);
    now.step=0;
    now.id=s;
    now.val=rd[s];
    while(!q.empty()) q.pop();
    q.push(now);
    while(!q.empty()) {
        pre=q.front();
        q.pop();
        if(pre.id==f) {
            ans=max(ans,pre.val);
            continue;
        }
        int u=pre.id;
        int len=g[u].size();
        for(int i=0; i<len; i++) {
            int v=g[u][i];
            now.val=min(pre.val,rd[v]);
            now.step=pre.step+1;
            if(now.step==sd[v]&&d[v]<now.val) {
                d[v]=now.val;
                now.id=v;
                q.push(now);
            }
        }
    }
}
int main() {
    int n,m,u,v,s,f,r;
    while(~scanf("%d%d",&n,&m)) {
        for(int i=1;i<=n;i++) g[i].clear();
        while(m--) {
            scanf("%d%d",&u,&v);
            g[u].push_back(v);
            g[v].push_back(u);
        }
        scanf("%d%d%d",&s,&f,&r);
        bfs(s,sd);
        bfs(r,rd);
        solve(s,f);
        printf("%d\n",ans);
    }
    return 0;
}


L题:分情况讨论:
         (1)若x+y<C ,无解
         (2)若x+y=C , 单一解,即X,Y
         (3)若x+y>C,如果x<= C,a=x,b=C-x
                               否则,如果y<=C , a=C-y , b=y
                                          否则a=0,b=C

        当然这题是开放题,仁者见仁智者见智~

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>

#define LL __int64
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;

LL x,y,c;

int main() {
    while(~scanf("%I64d%I64d%I64d",&x,&y,&c)) {
        if(x+y==c) {
            printf("%I64d %I64d\n",x,y);
            continue;
        }
        if(x+y<c) {
            puts("Impossible");
            continue;
        }

        LL a,b;

        if(x<=c){
            a=x;
            b=c-x;
        }
        else{
            if(y<=c){
                a=c-y;
                b=y;
            }
            else{
                a=0;
                b=c;
            }
        }

        printf("%I64d %I64d\n",a,b);

    }

    return 0;
}
/**
100000000 100000000 100000000
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值