训练8

 

5097: Magic Squares

#include<bits/stdc++.h>
using namespace std;
string s;
map<string,string> m;
queue<string> q;
void A(string a)
{
    string b;
    for(int i=7;i>=4;i--)
    {
        b+=a[i];
    }
    for(int i=3;i>=0;i--)
    {
        b+=a[i];
    }
    if(!m.count(b))
    {
        m[b]=m[a]+'A';
        q.push(b);
    }
}
void B(string a)
{
    string b;
    b+=a[3];
    for(int i=0;i<3;i++)
    {
        b+=a[i];
    }
    for(int i=5;i<8;i++)
    {
        b+=a[i];
    }
    b+=a[4];
    if(!m.count(b))
    {
        m[b]=m[a]+'B';
        q.push(b);
    }
}
void C(string a)
{
    string b=a;
    b[1]=a[6];
    b[2]=a[1];
    b[5]=a[2];
    b[6]=a[5];
    if(!m.count(b))
    {
        m[b]+=m[a]+'C';
        q.push(b);
    }
}
void bfs()
{
    q.push("12345678");
    while(q.size())
    {
        A(q.front());
        B(q.front());
        C(q.front());
        if(m.count(s)!=0)
        {
            cout<<m[s].size()<<endl;
            cout<<m[s]<<endl;
            break;
        }
        q.pop();
    }
}
int main()
{
    for(int i=1;i<=8;i++)
    {
        char x;
        scanf("%c",&x);
        getchar();
        s+=x;
    }
    bfs();
}

//广搜

2790: Dominos 2

题意:多米诺骨牌,求有多少骨牌会被推掉

#include<bits/stdc++.h>
using namespace std;
vector<int> v[10005];
int vis[10005],num;
void dfs(int z)
{
    vis[z]=1;
    num++;
    for(int i=0;i<v[z].size();i++)
    {
        if(vis[v[z][i]]==0)
        {
            dfs(v[z][i]);
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m,l;
        memset(vis,0,sizeof(vis));
        scanf("%d%d%d",&n,&m,&l);
        for(int i=0;i<=n;i++)
        {
            v[i].clear();
        }
        for(int i=1;i<=m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            v[x].push_back(y);
        }
        num=0;
        for(int i=1;i<=l;i++)
        {   int z;
            scanf("%d",&z);
            if(vis[z]==0)dfs(z);
        }
        printf("%d\n",num);
    }
}

//深搜

6061: Bomb

题意:给一个数n,求1~n中包含49的数的个数

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll d;
ll dp[25][3];
void init()
{
    dp[0][0]=1;//dp[i][0]表示i位数内不含49的个数
    dp[0][1]=dp[0][2]=0;//dp[i][1]表示i位数内以9为首的不含49的个数
    for(int i=1;i<20;i++) //dp[i][2]表示i位数内含49的个数
    {
        dp[i][0]=10*dp[i-1][0]-dp[i-1][1];
        dp[i][1]=dp[i-1][0];
        dp[i][2]=10*dp[i-1][2]+dp[i-1][1];
    }
}
ll check(ll d)
{
     int num[25]={0},len=0;
     while(d>0)
     {
         num[++len]=d%10;
         d/=10;
     }
     ll sum=0;
     int flag=0;
     for(int i=len;i>=1;i--)//逐位添加
     {
         sum+=dp[i-1][2]*num[i];
         if(flag)
         sum+=dp[i-1][0]*num[i];
         else
         {
             if(num[i]>4)sum+=dp[i-1][1];
         }
         if(num[i+1]==4&&num[i]==9)flag=1;
     }
     if(flag)sum++;
     return sum;
}
int main()
{
    int t;
    init();
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld",&d);
        printf("%lld\n",check(d));
    }
}

//数位dp

6067: LCM Walk

题意:从起点(x,y)开始可向上或者向右移动lcm(x,y)步,现在给出一个终点,求有多少个点作为起点可到达该终点

思路:设起点为(qt,pt),t为最小公因数,最小公倍数为qpt,故终点为(qt,pt+qpt)--->(qt,(1+q)pt), 因此可逆推出 终点(x,y),x<y时,若y%(x+1)==0则有一个点可作为起始点

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int t;
    scanf("%d",&t);
    for(int i=1;i<=t;i++)
    {
        long long  a,b,num=1;
        scanf("%lld%lld",&a,&b);
        printf("Case #%d: ",i);
        int d=__gcd(a,b);
        a/=d;
        b/=d;
        while(1)
        {
           if(a>b)swap(a,b);
           if(b%(a+1))
                break;
           b=b/(a+1);
           num++;
        }
        printf("%lld\n",num);
    }
}

//逆推

6072: sum

题意:求一个序列的连续子序列之和能否被m整除

#include<bits/stdc++.h>
using namespace std;
int num[5005];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {   int n,m;
        scanf("%d%d",&n,&m);
        int flag=0,sum=0;
        memset(num,0,sizeof(num));
        for(int i=1;i<=n;i++)
        {
            int x;
            scanf("%d",&x);
            sum+=x;
            if(sum%m==0)flag=1;//前缀和被m整除
            if(num[sum%m]==1)flag=1;//当序列的前缀和出现两次除m余数相同时,说明,连续子序列和存在被m整除的情况
            num[sum%m]++;
        }
        if(flag)printf("YES\n");
        else
        printf("NO\n");
    }
}

 

6074: Shopping

题意:先给出n个店的店名,再给出m个n行,每行为涨价值以及对应的店名,求memory店铺的商品价值在所有店铺商品价值的排名

#include<bits/stdc++.h>
using namespace std;
map<string,int> m;
int money[10005];
int main()
{
    int n,t,flag;
    scanf("%d",&n);
    getchar();
    for(int i=1;i<=n;i++)
    {
        string s;
        char ch;
        while(ch=getchar())
        {
            if(ch=='\n')break;
            s+=ch;
        }
        m[s]=i;
        if(s=="memory")
            flag=i;
    }
    scanf("%d",&t);
    while(t--)
    {
        for(int i=1;i<=n;i++)
        {
            int in;
            scanf("%d",&in);
            string s;
            char ch;
           getchar();
           while(ch=getchar())
           {
            if(ch=='\n')break;
            s+=ch;
           }
            money[m[s]]+=in;
        }
        int sum=0;
        for(int i=1;i<=n;i++)
        {
            if(money[i]>money[flag])sum++;
        }
        printf("%d\n",sum+1);
    }
}

//map容器

6083: Rank of Tetris

题意:"A > B","A = B","A < B"根据这三类信息判断信息是冲突,是否完整。 

#include<bits/stdc++.h>
using namespace std;
int x[20005],y[20005],f[10005],in[20005];
vector<int> vec[10005];
char ch[20005];
int n,m;
int find(int x)
{
    return f[x]==x?x:find(f[x]);
}
void work()
{
    queue<int> q;
    int num=0,ans=0;
    for(int i=1;i<=n;i++)
    {
        int t1=find(i);
        if(t1==i)
        {
           if(in[t1]==0)
           q.push(t1);//添加0入度点进入队列
           num++;//记录点数
        }
    }
    int flag=0;
    while(q.size())
    {
        if(q.size()>1)//队列出现超过一个元素,说明信息不完整,有至少一对点的大小关系不能确定
        {
            flag=1;
        }
        int z=q.front();
        q.pop();
        ans++;
        for(int i=0;i<vec[z].size();i++)
        {
            int t1=find(vec[z][i]);
            in[t1]--;
            if(in[t1]==0)q.push(t1);
        }
    }
    if(ans!=num)
        printf("CONFLICT\n");
    else
    {
        if(flag)
        printf("UNCERTAIN\n");
        else
        printf("OK\n");
    }
}

//并查集+拓扑排序

posted on 2019-11-03 22:08  还是力量不够  阅读(151)  评论(0)    收藏  举报

导航