第十五届“华为杯”大学生程序设计竞赛题解

1.虢莔薅参加运动会

解法:1^2+2^2+3^2+...n^2=n*(n+1)*(2*n+1)/6代入求解,注意6的逆元求法

题目类型:数论裸题

#include 
#define ll long long
using namespace std;
ll n,p;
ll pow_mod(ll a,ll x,ll p)
{
    ll tmp=a%p,ans=1;
    while(x>=1)
    {
        if(x%2==1)
            ans=ans*tmp%p;
        tmp=tmp*tmp%p;
        x>>=1;
    }
    return ans;
}
ll inv(ll a,ll p)
{
    ll ans=1;
    ans=pow_mod(a,p-2,p);
    return ans;
}
int main()
{
    while(scanf("%lld%lld",&n,&p)!=EOF)//1^2+2^2+3^2+...n^2=n*(n+1)*(2*n+1)/6代入求解,注意6的逆元
    {
        ll INV=inv(6,p);
        //printf("--%lld\n",INV);
        ll res=n%p*(n+1)%p*(2*n+1)%p*INV%p;
        printf("%lld\n",res);
    }
    return 0;
}

2.统计相似字符串

题意:统计含有完全相同的字符的字符串,并输出

解法:map< string , queue >(现场脑洞這个好用啊)

#include 
#define ll long long
using namespace std;
int n;
string s[6005],c;
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        queue q;
        map > m;
        for(int i=0;i>s[i];
            c=s[i];
            sort(c.begin(),c.end());
            m[c].push(s[i]);
            q.push(c);
        }
        while(!q.empty())
        {
            int flag=0;
            string ts=q.front();
            q.pop();
            while(!m[ts].empty())
            {
                if(flag)cout<<" ";
                cout << m[ts].front();
                m[ts].pop();
                flag=1;
            }
            if(flag)
            cout<
3.V8与女友

题目类型:最短路

解法:求出最短路,乘2

(顺便存个SPFA模板):

#include
#include
#include
#include
#define M 100010
#define N 20010
#define INF 1e9
//spfa模板
using namespace std;

int v[M], u[M], w[M], first[N], nex[M];
queue  q;
int n, m, s, t, edge_num;
int d[N], inq[N];

void addedge(int x, int y, int z)
{
    int &e = edge_num;
    u[e] = x; v[e] = y; w[e] = z;
    nex[e] = first[u[e]];
    first[u[e]] = e;
    e++;
    u[e] = y; v[e] = x; w[e] = z;
    nex[e] = first[u[e]];
    first[u[e]] = e;
    e++;
}

int SPFA(int a, int b)
{
    for (int i = 0; i < n; i++) d[i] = (i == a) ? 0 : INF;
    memset(inq, 0, sizeof(inq));
    q.push(a); inq[a] = true;
    while (!q.empty()) {
        int x = q.front(); q.pop();
        inq[x] = false;
        for (int e = first[x]; e != -1; e = nex[e]) if (d[v[e]] > d[x] + w[e]) {
            d[v[e]] = d[x] + w[e];
            if (!inq[v[e]]) {
                inq[v[e]] = true;
                q.push(v[e]);
            }
        }
    }
    return d[b];
}

int main()
{
    int tests;
    int d = 0;
    scanf("%d", &tests);
    while (tests--) {
        d++;
        edge_num = 0;
        memset(first, -1, sizeof(first));
        scanf("%d",&m);
        n=10003;//节点数
        for (int i = 0; i < m; i++) {
            int x, y, z;
            scanf("%d%d%d", &x, &y, &z);
            addedge(x, y, z);
        }
        scanf("%d%d",&s,&t);
        int ans = SPFA(s,t);
        printf("%d\n", 2*ans);
    }
    return 0;
}
4.大红数星星(学习了大佬题解做法)

题意:无向图判断三元环数目;

解法:枚举一条边,判断左右端点的邻集,顺序去重

#include 
#define ll long long
using namespace std;
vector G[100001];
int u[100001],v[100001];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            G[i].clear();
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&u[i],&v[i]);
            if(u[i]>v[i])swap(u[i],v[i]);
            G[u[i]].push_back(v[i]);
        }
        for(int i=1;i<=n;i++)
        {
            sort(G[i].begin(),G[i].end());
        }
        ll ans=0;
        for(int i=1;i<=m;i++)
        {
            vector::iterator iu=G[u[i]].begin(),iv=G[v[i]].begin();
            for(;iu!=G[u[i]].end();iu++)
            {
                while(iv!=G[v[i]].end()&&*iv<*iu)
                    iv++;
                if(iv==G[v[i]].end())
                    break;
                if(*iv==*iu)
                    ans++;
            }
        }
         cout << ans<< endl;
    }
    return 0;
}






你可能感兴趣的:(第十五届“华为杯”大学生程序设计竞赛题解)