A 勘测:
题目:
思路:
找规律,通过找出前几天的建设道路的次数发现为斐波那契额数列,然后求前n项的和即可。
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=10000000007;
const int maxn=5*1e6+5;
int n;
ll a[maxn];
ll sum[maxn];
int main()
{
scanf("%d",&n);
memset(sum,0,sizeof(sum));
a[0]=0;sum[0]=0;a[1]=1;a[2]=2;
sum[1]=1;sum[2]=3;
for (int i=3;i<=n;i++)
{
a[i]=(a[i-1]+a[i-2])%mod;
sum[i]=(sum[i-1]+a[i])%mod;
}
printf("%lld\n",sum[n]%mod);
return 0;
}
B 数学:
题目:
思路:
根据3,5,8,11倍数的特性来进行判定。
如果不知道倍数特性的话可以看看下面这篇博客:
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
string a;
int is[4];
int on[4]={3,5,8,11};
int num=0;
void Judge()
{
int sum=0,sumo=0,sume=0,sum8=0;
for (int i=0;i<a.length();i++)
{
sum+=a[i]-'0';
if((i+1)%2)
sumo+=a[i]-'0';
else
sume+=a[i]-'0';
}
if(sum%3==0)
is[0]=1,num++;
if(a[a.length()-1]=='0'||a[a.length()-1]=='5')
is[1]=1,num++;
for (int i=a.length()-1,j=0,k=1;i>=0&&j<3;i--,j++,k*=10)
sum8=sum8+(a[i]-'0')*k;
if(sum8%8==0)
is[2]=1,num++;
if(abs(sumo-sume)%11==0)
is[3]=1,num++;
}
int main()
{
cin>>a;
memset (is,0,sizeof(is));
Judge();
if(num)
{
printf("Yes\n");
for (int i=0;i<4;i++)
{
if(is[i])
{
printf("%d ",on[i]);
num--;
}
}
printf("\n");
}
else
{
printf("No\n");
}
return 0;
}
C 约数
题目:
思路:
求出a,b的gcd, 然后对gcd进行分解。
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a,b;
vector<ll>ans;
ll gcd (ll a,ll b)
{
return b==0?a:gcd(b,a%b);
}
int main()
{
scanf("%lld%lld",&a,&b);
ll g=gcd(a,b);
for (ll i=1;i<=sqrt(g);i++)
{
if(g%i==0)
{
ans.push_back(i);
if(i*i!=g)
ans.push_back(g/i);
}
}
sort(ans.begin(),ans.end());
for (int i=0;i<ans.size();i++)
{
printf("%lld%c",ans[i],i==ans.size()-1?'\n':' ');
}
return 0;
}
D 饥饿
题目:
思路:
将安全的道路建图, 然后套用迪杰斯特拉算法。
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF=9223372036854775807;
const int maxn=1e6+5;
int head[maxn];
int n,m,s,t;
ll d[maxn];
struct edge
{
int to;
int next;
ll len;
};
edge e[200005*4];
void addedge (int id,int u,int v,ll len)
{
e[id].to=v;
e[id].len=len;
e[id].next=head[u];
head[u]=id;
}
void djst()
{
int vis[maxn];
memset(vis,0,sizeof(vis));
for (int i=0;i<=n;i++)
{
d[i]=INF;
}
d[s]=0;
while (1)
{
ll Max=INF;
int u=-1;
for (int i=1;i<=n;i++)
{
if(!vis[i]&&Max>d[i])
{
Max=d[i];
u=i;
}
}
if(u==-1)
break;
vis[u]=1;
for (int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
ll len=e[i].len;
if(!vis[i]&&d[u]+len<d[v])
{
d[v]=d[u]+len;
}
}
}
if(d[t]==INF)
printf("My gold!!!\n");
else
printf("%lld\n",d[t]);
}
int main()
{
scanf("%d%d%d%d",&n,&m,&s,&t);
memset (head,-1,sizeof(head));
for (int i=0,id=0;i<m;i++)
{
int flag,x,y;
ll len;
scanf("%d%d%d%lld",&flag,&x,&y,&len);
if(flag)
{
addedge(id++,x,y,len);
addedge(id++,y,x,len);
}
}
djst();
return 0;
}