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;
}