山东省第六届ACM省赛

ID.Title Hint
A.Nias and Tug-of-War sort排序
B.Lowest Unique Price set+map
C.Game! 博弈
D.Stars  
E.BIGZHUGOD and His Friends I 赛瓦定理
F.BIGZHUGOD and His Friends II 赛瓦定理 
G.Cube Number 质因数分解
H.Square Number 质因数分解
I.Routing Table  
J.Single Round Math 大数
K.Last Hit  
L.Circle of Friends 缩点

A.Nias and Tug-of-War

s.sort排序

#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;

struct node{
    double a;
    double b;
}a[105];

bool cmp(node a,node b){
    //if(a.a!=b.a)
    return a.a<b.a;//a升
    //return a.b>b.b;//b降
}

int main(){

    int T;
    int N;
    int i;
    double sum1,sum2;

    scanf("%d",&T);

    while(T--){

        scanf("%d",&N);

        for(i=0;i<N;++i){
            scanf("%lf%lf",&a[i].a,&a[i].b);
        }

        sort(a,a+N,cmp);

        sum1=0;
        for(i=0;i<N;i+=2){
            sum1+=a[i].b;
        }
        sum2=0;
        for(i=1;i<N;i+=2){
            sum2+=a[i].b;
        }

        if(sum1>sum2){
            printf("red
");
        }
        else if(sum2>sum1){
            printf("blue
");
        }
        else{//避免比较相等
            printf("fair
");
        }
    }


    return 0;
}
View Code

B.Lowest Unique Price

s.set+map

#include<iostream>
#include<stdio.h>
#include<set>
#include<map>
using namespace std;

int main(){

    int T;
    int N;
    char str[2];
    int x;
    int i;
    set<int> myset;
    map<int,int> mymap;

    scanf("%d",&T);

    while(T--){

        myset.clear();
        mymap.clear();

        scanf("%d",&N);

        for(i=0;i<N;++i){
            scanf("%1s",str);

            if(str[0]=='b'){
                scanf("%d",&x);
                myset.insert(x);
                ++mymap[x];
                if(mymap[x]>1){//多于一次价格x
                    myset.erase(x);
                }
            }
            else if(str[0]=='c'){
                scanf("%d",&x);
                --mymap[x];
                if(mymap[x]==0){//撤销一次没有价格x
                    myset.erase(x);
                }
                else if(mymap[x]==1){//撤销一次只剩一次价格x
                    myset.insert(x);
                }
            }
            else{
                if(!myset.empty()){
                    printf("%d
",*myset.begin());
                }
                else{
                    printf("none
");
                }
            }

        }

    }

    return 0;
}
View Code

C.Game!

s.博弈。当石子个数大于2时,后手赢。

还得看看博弈,做做题。

#include<iostream>
#include<stdio.h>
using namespace std;

int main(){

    int T;
    long long N;

    scanf("%d",&T);

    while(T--){

        scanf("%lld",&N);

        if(N>2){
            printf("blankcqk
");
        }
        else{
            printf("zbybr
");
        }

    }

    return 0;
}
View Code

D.Stars

E.BIGZHUGOD and His Friends I

F.BIGZHUGOD and His Friends II

G.Cube Number

d.Given an array of distinct integers (a1, a2, ..., an), you need to find the number of pairs (ai, aj) that satisfy (ai * aj) is a cube number.

s.和下个平方数类似,不错凑立方数的时候,不是从某个数中选2个数了,而是根据这个数的质因数的个数,把每个质因数凑成3个,这样可能直接用这个数乘上相应的数就行了。

ps:long long,还有数组越界的判断搞了好久。。

/*
质因数分解
*/
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
using namespace std;

const int MAXN=100;
const long long MAXN2=1000000+10;//数字范围

long long num[MAXN2];

int factors[MAXN][2];//[0]存质因子,[1]存个数
int factCnt;//不同的质因子总个数

int getFactors(int n){

    int i,k;
    factCnt=0;
    for(i=2,k=sqrt(n);i<=k;++i){
        if(n%i==0){
            factors[factCnt][0]=i;
            factors[factCnt][1]=1;
            n=n/i;
            while(n%i==0){
                ++factors[factCnt][1];
                n=n/i;
            }
            ++factCnt;
            k=sqrt(n);//循环条件不直接写i<=sqrt(n);是因为这样可以避免重复开跟方
        }
    }
    if(n>1){
        factors[factCnt][0]=n;
        factors[factCnt][1]=1;
        ++factCnt;
    }

    int temp=1;
    int j;
    for(i=0;i<factCnt;++i){
        factors[i][1]=factors[i][1]%3;
        if(factors[i][1]!=0){
            for(j=0;j<factors[i][1];++j){
                temp=temp*factors[i][0];
            }
        }
    }
    return temp;
}

int main(){
    int T;
    int N;
    int t;
    int i,j,k;
    long long ans;
    long long tmp;
    int temp;
    bool flag;

    scanf("%d",&T);

    while(T--){
        scanf("%d",&N);
        memset(num,0,sizeof(num));
        for(i=0;i<N;++i){
            scanf("%d",&t);
            if(t==1){
                ++num[1];
                continue;
            }
            temp=getFactors(t);
            ++num[temp];
        }

        ans=0;
        for(i=2;i<MAXN2;++i){
            if(num[i]!=0){

                temp=getFactors(i);

                tmp=1;
                flag=true;
                for(j=0;j<factCnt;++j){
                    for(k=0;k<3-factors[j][1];++k){
                        tmp=tmp*factors[j][0];
                        if(tmp>=MAXN2){
                            flag=false;
                            break;
                        }
                    }
                    if(flag==false){
                        break;
                    }
                }

                if(tmp>=MAXN2){
                    continue;
                }

                if(num[tmp]!=0){
                    ans=ans+num[i]*num[tmp];
                }
            }
        }

        ans=ans/2;
        if(num[1]!=0){//1的时候特殊处理
            ans=ans+num[1]*(num[1]-1)/2;
        }

        printf("%lld
",ans);
    }

    return 0;
}
View Code

H.Square Number

d.Given an array of distinct integers (a1, a2, ..., an), you need to find the number of pairs (ai, aj) that satisfy (ai * aj) is a square number.

s.质因数分解。如果某个质因子的个数为偶数,直接去掉;为奇数时保留一个。这样就缩小了规模。

最后遍历一遍,如果某个数存在,那就从中选出2个就可构成一个平方数,这个数形成的平方数的总个数就是C(n,2)。

/*
质因数分解
*/
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
using namespace std;

const int MAXN=102400;

int factors[MAXN][2];//[0]存质因子,[1]存个数
int factCnt;//不同的质因子总个数

#define MAXN2 1000000+10
int num[MAXN2];

void getFactors(int n){
    int i,k;
    factCnt=0;
    for(i=2,k=sqrt(n);i<=k;++i){
        if(n%i==0){
            factors[factCnt][0]=i;
            factors[factCnt][1]=1;
            n=n/i;
            while(n%i==0){
                ++factors[factCnt][1];
                n=n/i;
            }
            ++factCnt;
            k=sqrt(n);//循环条件不直接写i<=sqrt(n);是因为这样可以避免重复开跟方
        }
    }
    if(n>1){
        factors[factCnt][0]=n;
        factors[factCnt][1]=1;
        ++factCnt;
    }

    int temp=1;
    for(i=0;i<factCnt;++i){
        factors[i][1]=factors[i][1]%2;
        if(factors[i][1]!=0){
            temp=temp*factors[i][0];
        }
    }

    ++num[temp];

}



int main(){
    /*
    int n;
    while(~scanf("%d",&n)){

        getFactors(n);

        printf("不同的质因子总个数:%d
",factCnt);

        int i,j;
        for(i=0;i<factCnt;++i){
            for(j=0;j<factors[i][1];++j){
                printf("%d ",factors[i][0]);
            }
        }

        printf("
");
    }
    */
    int T;
    int N;
    int t;
    int i;
    int ans;
    int j;

    scanf("%d",&T);

    while(T--){
        scanf("%d",&N);
        memset(num,0,sizeof(num));
        for(i=0;i<N;++i){
            scanf("%d",&t);
            if(t==1){
                ++num[1];
                continue;
            }
            getFactors(t);
        }

        ans=0;
        for(i=0;i<MAXN2;++i){

            if(num[i]!=0){
                //cout<<i<<" "<<num[i]<<endl;
                ans=ans+(num[i]*(num[i]-1))/2;
            }
        }

        printf("%d
",ans);
    }

    return 0;
}
View Code

c2.这个代码可以参考下。

#include <stdio.h>
#include <string.h>
#define MAX 1000010
int pri[1010];
int dp[200];
int vis[MAX];
int amount=0;
void init()
{
    for(int i=2;i<=1000;i++)
    {//素数打表 
        for(int j=i+i;j<=1000;j+=i)
        {
            if(!pri[j])
                pri[j]=1;
        }
    }
    //平方数打表 
    for(int i=2;i<=1000;i++)
        if(!pri[i])
            dp[amount++]=i*i;
}

int main()
{
    int T,n;
    int t;
    int i,j;
    init();
    scanf("%d",&T);
    while(T--)
    {
        memset(vis,0,sizeof(vis));
        int ans=0;
        scanf("%d",&n);
        for(i=0;i<n;i++)
        {
            scanf("%d",&t);
            for(j=0;j<amount;j++)
            {
                if(t%dp[j]==0)
                {
                    while(t%dp[j]==0)
                        t/=dp[j];
                }
            }
            ans+=vis[t];
            //除去平方因数后的值 ,有多少个该平方因数的值就可以组成多少对 
            vis[t]++;
        }
        printf("%d
",ans);
    }
    return 0;
}
View Code

I.Routing Table

J.Single Round Math

s.唯一比较坑的是N要等于M,然而并没从题意看出来。。

c.java大数,注意类名要为Main

import java.math.BigInteger;
import java.util.Scanner;

public class Main {//类名要用Main
    public static void main(String[] args){
        
        int T;
        BigInteger N,M;
        BigInteger MOD=new BigInteger("11");
        BigInteger ZERO=new BigInteger("0");
        Scanner sc=new Scanner(System.in);
        
        T=sc.nextInt();
        while((T--)>0){
            
            N=sc.nextBigInteger();
            M=sc.nextBigInteger();
            
            if(N.compareTo(M)==0&&N.mod(MOD).compareTo(ZERO)==0){//
                System.out.println("YES");
            }
            else{//
                System.out.println("NO");
            }
            
        }
        
    }
}
View Code

K.Last Hit

L.Circle of Friends

d.

s.强连通分量缩点

ps:这里这个缩点方式可能有重边。

我感觉用set可能解决重边的问题。

另外缩点应该用桥来缩比较好。(好像发现是无向图有桥。。。)

/*
Tarjan算法
复杂度O(N+M)
*/
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;

const int MAXN=100000+10;//点数
const int MAXM=100000+10;//边数
struct Edge{
    int to,next;
}edge[MAXM];
int head[MAXN],tot;
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组的值是1~scc
int Index,top;
int scc;//强连通分量的个数
bool Instack[MAXN];
int num[MAXN];//各个强连通分量包含点的个数,数组编号1~scc
//num数组不一定需要,结合实际情况

void addedge(int u,int v){
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}
void Tarjan(int u){
    int v;
    Low[u]=DFN[u]=++Index;
    Stack[top++]=u;
    Instack[u]=true;
    for(int i=head[u];i!=-1;i=edge[i].next){
        v=edge[i].to;
        if(!DFN[v]){
            Tarjan(v);
            if(Low[u]>Low[v])Low[u]=Low[v];
        }
        else if(Instack[v]&&Low[u]>DFN[v])
            Low[u]=DFN[v];
    }
    if(Low[u]==DFN[u]){
        scc++;
        do{
            v=Stack[--top];
            Instack[v]=false;
            Belong[v]=scc;
            num[scc]++;
        }
        while(v!=u);
    }
}
void solve(int N){
    memset(DFN,0,sizeof(DFN));
    memset(Instack,false,sizeof(Instack));
    memset(num,0,sizeof(num));
    Index=scc=top=0;
    for(int i=0;i<N;i++)
        if(!DFN[i])
            Tarjan(i);
}
void init(){
    tot=0;
    memset(head,-1,sizeof(head));
}

int N,M;
struct Node{
    int u;
    int steps;
};
vector<int> g[MAXN];
int ans;
void bfs(){
    queue<Node> myQueue;

    Node tmp;
    tmp.u=Belong[0];
    tmp.steps=0;

    myQueue.push(tmp);

    Node u,v;
    int i;

    while(!myQueue.empty()){

        u=myQueue.front();
        myQueue.pop();

        if(u.u==Belong[N-1]){
            ans=u.steps;
            break;
        }

        for(i=0;i<g[u.u].size();++i){
            v.u=g[u.u][i];
            v.steps=u.steps+1;
            myQueue.push(v);
        }
    }
}

int main(){

    int T;
    //int N,M;
    int i,j;
    int u,v;
    int a,b;
    scanf("%d",&T);

    while(T--){
        init();
        scanf("%d%d",&N,&M);
        for(i=0;i<M;++i){
            scanf("%d%d",&u,&v);
            addedge(u,v);
        }
        solve(N);

        for(i=1;i<=scc;++i){
            g[i].clear();
        }
        for(i=0;i<N;++i){
            for(j=head[i];j!=-1;j=edge[j].next){
                a=Belong[i];
                b=Belong[edge[j].to];
                if(a!=b){

                    g[a].push_back(b);
                }
            }
        }

        ans=-1;
        bfs();
        printf("%d
",ans);
    }

    return 0;
}
View Code
原文地址:https://www.cnblogs.com/gongpixin/p/5327870.html