2017西电第一次省赛选拔赛补题

https://vjudge.net/contest/161101#overview


A.判断B是否能整除A的每一个素因子。

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

int prime[1000005],vis[1000005] = {0};
long long a,b;

int main()
{
    ios::sync_with_stdio(false);
    int T,z = 0;
    cin >> T;
    int cnt = 0;
    for(int i = 2;i <= 1000000;i++)
    {
        if(!vis[i]) prime[++cnt] = i;
        for(int j = 1;i*prime[j] <= 1000000 && j <= cnt;j++)
        {
            vis[prime[j]*i] = 1;
            if(i%prime[j] == 0) break;
        }
    }
    while(T--)
    {
        cin >> a >> b;
        cout << "Case #" << ++z << ": ";
        int flag = 0;
        for(int i = 1;(long long)prime[i]*prime[i] <= a;i++)
        {
            if(a%prime[i] == 0)
            {
                while(a%prime[i] == 0)  a /= prime[i];
                if(b%prime[i]) flag = 1;
            }
        }
        if(b%a) flag = 1;
        if(flag)    cout << "NO" << endl;
        else    cout << "YES" << endl;
    }
    return 0;
}
View Code

B.显然,最优解是每次选择一个人就把他HP耗尽。假设只有两个人,则

先攻击第一个人消耗:DPS1HP1+DPS2(HP1+HP2)

先攻击第二个人消耗:DPS2HP2+DPS1(HP1+HP2)

可以得出当DPS1/HP1 > DPS2/HP2时,攻击第一个人消耗小。

由此推广到n个人的情况,按DPSi/HPi排序即可。

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

int n;
struct xx
{
    int hp,dps;
    friend bool operator <(xx a,xx b)
    {
        return a.dps*b.hp > a.hp*b.dps;
    }
}a[25];

int main()
{
    ios::sync_with_stdio(false);
    while(cin >> n)
    {
        for(int i = 1;i <= n;i++)   cin >> a[i].dps >> a[i].hp;
        sort(a+1,a+1+n);
        int ans = 0,sum = 0;
        for(int i = 1;i <= n;i++)
        {
            sum += a[i].hp;
            ans += sum*a[i].dps;
        }
        cout << ans << endl;
    }
    return 0;
}
View Code

C.先把前一半的密文翻译乘明码,KMP求后半的在前半的最长前缀。

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

string s,ss;
int nextt[200005];
map<char,char> mp;

void get_next(string s)
{
    int len = s.length();
    int i = 0,j = -1;
    nextt[0] = -1;
    while(i < len)
    {
        if(j == -1 || s[i] == s[j]) nextt[++i] = ++j;
        else    j = nextt[j];
    }
}

int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        cin >> ss >> s;
        for(int i = 0;i < ss.length();i++)  mp[ss[i]] = i+'a';
        int len = s.length(),endd = (len+1)/2;
        string sss = s;
        for(int i = 0;i < endd;i++) s[i] = mp[s[i]];
        s.insert(endd,1,'+');
        get_next(s);
        int cnt = len-nextt[len+1];
        for(int i = 0;i < cnt;i++)  cout << sss[i];
        for(int i = 0;i < cnt;i++)  cout << mp[sss[i]];
        cout << endl;
    }
    return 0;
}
View Code

D.set模拟,注意连续在一个点吃的时候,方向不改变。

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

int n,m,cnt[100005];
set<int> s;
set<int>::iterator it;

int main()
{
    ios::sync_with_stdio(false);
    int T,z = 0;
    cin >> T;
    while(T--)
    {
        s.clear();
        memset(cnt,0,sizeof(cnt));
        cin >> n >> m;
        int dir = 2,now = 0;
        long long ans = 0;
        while(m--)
        {
            int a,b;
            cin >> a;
            if(a == 0)
            {
                cin >> b;
                if(cnt[b] == 0) s.insert(b);
                cnt[b]++;
            }
            else
            {
                if(s.size() == 0)   continue;
                it = s.lower_bound(now);
                int x = 1e9,y = 1e9;
                if(it != s.end())   y = *it-now;
                if(it != s.begin())
                {
                    it--;
                    x = now-*it;
                    it++;
                }
                if(it != s.end() && now == *it);
                else if(x < y || x == y && dir == 1)
                {
                    it--;
                    ans += x;
                    dir = 1;
                }
                else
                {
                    ans += y;
                    dir = 2;
                }
                now = *it;
                cnt[*it]--;
                if(cnt[*it] == 0)   s.erase(it);
            }
        }
        cout << "Case " << ++z << ": " << ans << endl;
    }
}
View Code

E.因为每两个点之间有且只有一条单向边,拓扑排序判断是否存在环即可,有环肯定有三元环。

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

int n,in[2005];
string s;
vector<int> v[2005];

bool topsort()
{
    int cnt = 0;
    while(cnt < n)
    {
        int t;
        for(t = 1;t <= n;t++)
        {
            if(in[t] == 0)  break;
        }
        if(t == n+1)    return 1;
        in[t]--;
        cnt++;
        for(int i = 0;i < v[t].size();i++)
        {
            in[v[t][i]]--;
        }
    }
    return 0;
}

int main()
{
    ios::sync_with_stdio(false);
    int T,z = 0;
    cin >> T;
    while(T--)
    {
        cin >> n;
        for(int i = 1;i <= n;i++)   v[i].clear();
        memset(in,0,sizeof(in));
        for(int i = 1;i <= n;i++)
        {
            cin >> s;
            s = " "+s;
            for(int j = 1;j < s.length();j++)
            {
                if(s[j] == '1') in[j]++;
                v[i].push_back(j);
            }
        }
        cout << "Case #" << ++z << ": ";
        if(topsort())   cout << "Yes" << endl;
        else    cout << "No" << endl;
    }
    return 0;
}
View Code

F.逆序建树就可以了。

#include<iostream>
using namespace std;

struct xx
{
    xx *l,*r;
    char x;
}*root;
string s[10005];

void insertt(xx *&p,char x)
{
    if(p == NULL)
    {
        p = new xx;
        p->l = NULL;
        p->r = NULL;
        p->x = x;
        return;
    }
    if(p->x > x)    insertt(p->l,x);
    else    insertt(p->r,x);
}

void printff(xx *p)
{
    if(!p)  return;
    cout << p->x;
    printff(p->l);
    printff(p->r);
}

int main()
{
    ios::sync_with_stdio(false);
    while(1)
    {
        int n = 0;
        while(cin >> s[++n] && s[n] != "*" && s[n] != "$");
        root = NULL;
        for(int i = n-1;i >= 1;i--)
        {
            for(int j = 0;j < s[i].length();j++)    insertt(root,s[i][j]);
        }
        printff(root);
        cout << endl;
        if(s[n] == "$") break;
    }
    return 0;
}
View Code

G.Bretschneider公式

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

int a,b,c,d;

int main()
{
    ios::sync_with_stdio(false);
    int T,z = 0;
    cin >> T;
    while(T--)
    {
        cin >> a >> b >> c >> d;
        if(a+b+c <= d || a+c+d <= b || a+b+d <= c || b+c+d <= a)
        {
            cout << "Case " << ++z << ": -1" << endl;
            continue;
        }
        double t = (double)(a+b+c+d)/2;
        double ans = sqrt((t-a)*(t-b)*(t-c)*(t-d));
        cout << "Case " << ++z << ": " << fixed << setprecision(6) << ans << endl;
    }
    return 0;
}
View Code

H.找规律打个表。

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

long long n,a[50000];

int main()
{
    ios::sync_with_stdio(false);
    for(int i = 1;i <= 50000;i++) a[i] = (long long)i*(i-1);
    int T;
    cin >> T;
    while(T--)
    {
        cin >> n;
        int t = lower_bound(a+1,a+50000,n)-a-1;
        long long ans1 = (long long)t*t+n-a[t];
        long long ans2 = 0,now = 1;
        while(now*now < ans1)   ans2 += (now*now-(now-1)*(now-1))*(now-1),now++;
        ans2 += (ans1-(now-1)*(now-1)+1)*(now-1);
        cout << ans1 << " " << ans2 << endl;
    }
    return 0;
}
View Code

I.直接模拟加法。

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

string s;
int a[100005];

int main()
{
    ios::sync_with_stdio(false);
    int T;
    cin >> T;
    while(T--)
    {
        memset(a,0,sizeof(a));
        cin >> s;
        int sum = 0,cnt = 0;
        for(int i = s.length()-1;i >= 0;i--)
        {
            a[++cnt] = s[i]-'0';
            sum += a[cnt];
        }
        sum %= 10;
        do
        {
            if(a[1] != 9)
            {
                a[1]++;
                sum = (sum+1)%10;
            }
            else
            {
                int t = 1;
                a[1] = 0;
                sum = 0;
                for(int i = 2;i <= cnt;i++)
                {
                    if(t)
                    {
                        a[i]++;
                        if(a[i] == 10)  a[i] = 0;
                        else    t = 0;
                    }
                    sum += a[i];
                }
                if(t)
                {
                    a[++cnt] = 1;
                    sum++;
                }
                sum %= 10;
            }
        }while(sum != 0);
        int t = 100004;
        while(a[t] == 0)   t--;
        while(t >= 1)
        {
            cout << a[t];
            t--;
        }
        cout << endl;
    }
    return 0;
}
View Code

J.把所有U替换成I,打表所有可能的个数。

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

int n,ok[3000008];
string s;

int main()
{
    ios::sync_with_stdio(false);
    int now = 1;
    while(now <= 3000000)
    {
        ok[now] = 1;
        now *= 2;
    }
    for(int i = 3000000;i >= 1;i--)
    {
        if(ok[i+6])   ok[i] = 1;
    }
    int T;
    cin >> T;
    while(T--)
    {
        cin >> s;
        int flag = 0,sum = 0;
        if(s[0] != 'M') flag = 1;
        for(int i = 1;i < s.length();i++)
        {
            if(s[i] == 'M') flag = 1;
            else if(s[i] == 'U')    sum += 3;
            else    sum++;
        }
        if(flag == 0 && ok[sum])    cout << "Yes" << endl;
        else    cout << "No" << endl;
    }
    return 0;
}
View Code

 

posted @ 2017-05-05 01:05  zzzzzzzzhu  阅读(289)  评论(0编辑  收藏  举报