Hankson 的趣味题
一、题目
二、解法
gcd
\gcd
gcd和
lcm
\text{lcm}
lcm的实质是在对应的质数的指数上取
min max
\text{min max}
min max。
我们先把小于等于
n
\sqrt n
n的质数给筛出来,然后再用这些质数给
a
0
,
a
1
,
b
0
,
b
1
a_0,a_1,b_0,b_1
a0,a1,b0,b1质因数分解,然后我们对于每一个质数考虑,注意特判大于
n
\sqrt n
n的质数。
下面给我我带有注释的代码。
#include <cstdio>
const int MAXN = 50005;
int read()
{
int x=0,flag=1;char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int n,val[4],a[4][MAXN],a0,a1,b0,b1;
int cnt,p[MAXN],vis[MAXN];
void sieve(int n)
{
for(int i=2;i<=n;i++)
{
if(!vis[i]) p[++cnt]=i;
for(int j=1;j<=cnt && i*p[j]<=n;j++)
{
vis[i*p[j]]=1;
if(i%p[j]==0) break;
}
}
}
void dec(int num,int cur)
{
val[cur]=0;
for(int i=1;i<=cnt;i++)
{
a[cur][i]=0;
while(num%p[i]==0)
{
a[cur][i]++;
num/=p[i];
}
}
a[cur][cnt+1]=0;
if(num!=1) val[cur]=num,a[cur][cnt+1]=1;
}
int solve()
{
int res=1;
for(int i=1;i<=cnt+1;i++)//对于每一个质因数单独考虑
{
if(a[1][i]>a[3][i]) return 0;//如果a1某一个质因数的次数大于b1,那么无解,因为a1肯定是b1的因数
if(a[0][i]>a[1][i] && a[2][i]<a[3][i] && a[1][i]!=a[3][i]) return 0;//如果两个皆由x的所取次数决定,判断他们需要的次数相不相等
if(a[0][i]==a[1][i] && a[2][i]==a[3][i]) res*=(a[3][i]-a[1][i]+1); //乘法原理,在可行区间内皆可取到
}
return res;
}
int main()
{
sieve(5e4);//欧拉筛
n=read();
while(n--)
{
a0=read();a1=read();b0=read();b1=read();
dec(a0,0);dec(a1,1);
dec(b0,2);dec(b1,3);//质因数分解
if(val[1] && val[1]!=val[3])
{//判断大于sqrt的质因数的情况,要么就是a1没有大于sqrt的质因数,要么就是a1和b1的那个质因数相等
printf("0\n");
continue;
}
printf("%d\n",solve());
}
}
定价
一、题目
二、解法
其实这道题做法特别多,主要就是码量大。
讲一种贪心解法吧(毫无特判),就是找到
L
L
L最后的非零位,然后把它加1,边做边统计答案即可,其实这种贪心来源于保证0的个数单调递增是一定能取到答案的,上代码。
#include <cstdio>
#include <iostream>
using namespace std;
int read()
{
int x=0,flag=1;char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int n,ans,Min;
int change(int num)
{
int t=1;
while(num>0)
{
if(num%10) return t;
num/=10;
t*=10;
}
}
int calu(int num)
{
int a[10]={};
while(num>0)
{
a[++a[0]]=num%10;
num/=10;
}
for(int i=1;i<=a[0];i++)
if(a[i])
return (a[0]-i+1)*2-(a[i]==5);
}
int main()
{
n=read();
while(n--)
{
Min=20;
int L=read(),R=read();
while(L<=R)
{
int t=calu(L);
if(Min>t)
{
Min=t;
ans=L;
}
L+=change(L);
}
printf("%d\n",ans);
}
}
最优贸易
一、题目
二、解法
我的思路就是先缩点(其实缩不缩都一样),然后再仿照最短路的方法跑
spfa
\text{spfa}
spfa,注意还要跑一个反向图,来判断当前点是否能到达
n
n
n点,才更新答案。
写的有点长,勿喷。
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <cstring>
using namespace std;
const int MAXN = 100005;
int read()
{
int x=0,flag=1;char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int n,m,tot,Index,num,ans,a[MAXN],f[MAXN];
int dis[MAXN],Min[MAXN],Max[MAXN],dfn[MAXN],low[MAXN],mark[MAXN];
bool in[MAXN];
struct edge
{
int v,next;
}e[MAXN*10];
stack<int> s;
vector<int> G[MAXN],rg[MAXN];
void tarjan(int u)
{
dfn[u]=low[u]=++Index;
s.push(u);
in[u]=1;
for(int i=f[u];i;i=e[i].next)
{
int v=e[i].v;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(in[v])
low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
num++;
int v;
do
{
v=s.top();
s.pop();
in[v]=0;
mark[v]=num;
}while(v!=u);
}
}
void bfs()
{
queue<int> q;
q.push(mark[n]);
in[mark[n]]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=0;i<rg[u].size();i++)
{
int v=rg[u][i];
if(!in[v])
{
in[v]=1;
q.push(v);
}
}
}
}
void spfa()
{
memset(dis,0x3f,sizeof dis);
queue<int> q;
q.push(mark[1]);
dis[mark[1]]=Min[mark[1]];
while(!q.empty())
{
int u=q.front();
q.pop();
if(in[u]) ans=max(ans,Max[u]-dis[u]);
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(dis[v]>min(dis[u],Min[v]))
{
dis[v]=min(dis[u],Min[v]);
q.push(v);
}
}
}
}
int main()
{
memset(Min,0x3f,sizeof Min);
n=read();m=read();
for(int i=1;i<=n;i++)
a[i]=read();
for(int i=1;i<=m;i++)
{
int u=read(),v=read(),z=read();
e[++tot]=edge{v,f[u]},f[u]=tot;
if(z==2) e[++tot]=edge{u,f[v]},f[v]=tot;
}
for(int i=1;i<=n;i++)
if(!dfn[i])
tarjan(i);
for(int i=1;i<=n;i++)
{
Min[mark[i]]=min(Min[mark[i]],a[i]);
Max[mark[i]]=max(Max[mark[i]],a[i]);
for(int j=f[i];j;j=e[j].next)
{
int v=e[j].v;
if(mark[i]!=mark[v])
{
rg[mark[v]].push_back(mark[i]);
G[mark[i]].push_back(mark[v]);
}
}
}
bfs();
spfa();
printf("%d\n",ans);
}