acwing第44场周赛

1.不同正整数的个数

放在set中即可,set自动去重

#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
int main()
{
    int n;
    cin>>n;
    set<int> s;
    for(int i=0;i<n;i++)
    {
        int x;
        cin>>x;
        if(x) s.insert(x);
    }
    cout<<s.size();
    return 0;
}

2.最短路径 

 法1:

构造一个200*200的图,除了机器人走的路,其余全部设置为陷进,判断起点到终点的距离与机器人走法的最短距离是否相等

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 210;
typedef pair<int, int> PII;
#define x first
#define y second

int g[N][N];
int dist[N][N];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

int get(char c)
{
    //上右下左
    if(c=='U') return 0;
    if(c=='R') return 1;
    if(c=='D') return 2;
    return 3;
}

int bfs(int sx,int sy,int ex,int ey)
{
    memset(dist,-1,sizeof dist);
    dist[sx][sy]=0;
    queue<PII> q;
    q.push({sx,sy});
    
    while(q.size())
    {
        PII t=q.front();
        q.pop();
        for(int i=0;i<4;i++)
        {
            int x=t.x+dx[i];
            int y=t.y+dy[i];
            if(x<0||x>=N||y<0||y>=N) continue;
            if(g[x][y]==0) continue;
            if(dist[x][y]!=-1) continue;
            dist[x][y]=dist[t.x][t.y]+1;
            if(x==ex && y==ey) return dist[x][y];
            q.push({x,y});
        }
    }
    
    return -1;
}
int main()
{
    int x=N/2,y=N/2;
    g[x][y]=1;
    
    int sx=x,sy=y;
    
    string str;
    cin>>str;
    int d=str.size();
    
    for(int i=0;i<str.size();i++)
    {
        int dir=get(str[i]);
        x=x+dx[dir],y=y+dy[dir];
        g[x][y]=1;
    }
    int ex=x,ey=y;//终点
    
    if(bfs(sx,sy,ex,ey)==d) cout<<"YES";
    else cout<<"NO";
    return 0;
}

法2: 

1.最短路径首先不能有环:

判断是否走过重复的格子即可

2.不能相邻(要把走过来的那个格子特判掉)

 

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 210,B = N/2;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
bool st[N][N];//标记每个格子是否走过

int get(char c)
{
    if(c=='U') return 0;
    if(c=='R') return 1;
    if(c=='D') return 2;
    return 3;
}

int main()
{
    string str;
    cin>>str;
    
    bool flag=true;
    int x=B,y=B;
    st[x][y]=true;
    
    for(int i=0;i<str.size();i++)
    {
        int dir=get(str[i]);
        x=x+dx[dir];
        y=y+dy[dir];
        if(st[x][y]) flag=false;//1.判断是否有环
        
        for(int i=0;i<4;i++)
        {
            if(i!=(dir^2) && st[x+dx[i]][y+dy[i]])
            //dir^2表示0变2,1变3,dir是前面一个格子来到当前格子的方向,那么
            //从当前这个格子返回前面那个格子就是相反方向
            {
                flag=false;
                break;
            }
        }
        st[x][y]=true;
    }
    if(flag) cout<<"YES";
    else cout<<"NO";
    return 0;
}

 3.合适数对

算术基本定理:

所以 k | 每个ai,这样才能提取出k次方,每一个质因子的次数都是k的倍数

原题目就等价于

任意a[]中两个数ai和aj,ai*aj的所有质因子的次数都是k的倍数,有多少满足的序列对(ai,aj)

 枚举aj,求有多少个ai满足如下条件,质因子的次数之和是k的倍数

100000以内最多出现2,3,5,7,11,13这六个质因子

所以每一个a[]分解完质因子最多六项

假如aj分解完质因数后,有上面几项质因子的次数%k!=0(不是k的倍数),且%k结果分别是r1,r2,r3...

与之配对的t1=k-r1,t2=k-r2,t3=k-r3,...

哈希表解法

所以我们可以用哈希表来做

遍历a[],对于每一个a[],我们将其分解质因数,求出次数%k!=0的p1,p2,p3...,其%k的的值分别为r1,r2,r3,...

将p1^r1 * p2^r2 * p3^r3 *...放入哈希表  hash[p1^r1 * p2^r2 * p3^r3 *...]++

然后将与之对应的p1^t1(t1=k-r1) * p2^t2(t2=k-r2) * p3^t3(t3=k-r3) * ...也放入hash表

hash[p1^t1(t1=k-r1) * p2^t2(t2=k-r2) * p3^t3(t3=k-r3) * ...]++即可

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long LL;

const int N = 100010;
int n,k;
int cnt[N];

int qmi(int a,int b)
{
    LL res=1;
    while(b--)
    {
        res*=a;
        if(res>=N) return 0;
    }
    return res;
}


int main()
{
    cin>>n>>k;
    LL res=0;
    
    while(n--)
    {
        int x;
        cin>>x;
        LL y=1,z=1;//分别存p1^r1 * p2^r2 * p3^r3 *...和其互补的值
        for(int i=2;i<=x/i;i++)
        {
            if(x%i==0)
            {
                int s=0;
                while(x%i==0)
                {
                    s++;
                    x/=i;
                }
                s%=k;
                if(s) 
                {
                    y*=qmi(i,s);
                    z*=qmi(i,k-s);
                }
            }
        }
        if(x>1)
        {
            y*=x;
            z*=qmi(x,k-1);
        }
        if(z>=N) z=0;
        res+=cnt[z];
        cnt[y]++;
    }
    cout<<res;
    return 0;
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值