A. Good ol’ Numbers Coloring
题意:给你两个数
染色规则如下:
为白色; - 如果
,并且 是白色,那么 是白色; - 如果
,并且 是白色,那么 是白色; - 如果以上条件均不满足,那么这个数是黑色。
现在给定
解析:很明显,我们可以很快想到裴蜀定理:
在这个式子中,任意
所以如果
所以如果
所以直接判断是否互质就行了。
代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
int t,a,b;
int gcd(int a,int b)
{
if(b==0)
return a;
return gcd(b,a%b);
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&a,&b);
if(gcd(a,b)==1)
printf("Finite\n");
else
printf("Infinite\n");
}
return 0;
}
B. Restricted RPS
题意:给出对手的石头剪刀布的出牌顺序,一共比赛
解析:贪心题(为什么我考场上就做不对。。。,思路完全正确,码力有待加强)。能赢就赢,先把能够赢的次数用掉,最后再把剩下的次数随便用上去就行了。
代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
int t,n,a,b,c,ans;
char x[110],y[110];
int main()
{
scanf("%d",&t);
while(t--)
{
memset(x,0,sizeof(x));
memset(y,0,sizeof(y));
ans=0;
scanf("%d%d%d%d\n",&n,&a,&b,&c);
scanf("%s",x+1);
for(int i=1;i<=n;i++)
{
if(x[i]=='R'&&b>0)
{
y[i]='P';
b--;
ans++;
}
if(x[i]=='P'&&c>0)
{
y[i]='S';
c--;
ans++;
}
if(x[i]=='S'&&a>0)
{
y[i]='R';
a--;
ans++;
}
}
if(ans>=(n-n/2))
{
printf("YES\n");
for(int i=1;i<=n;i++)
if(!y[i])
{
if(a)
{
y[i]='R';
a--;
}
else if(b)
{
y[i]='P';
b--;
}
else
{
y[i]='S';
c--;
}
}
printf("%s\n",y+1);
}
else
printf("NO\n");
}
return 0;
}
C. Constanze’s Machine
题意:给你一个替换法则,法则如下:
- 所有的
m都要被替换为nn; - 所有的
w都要被替换为uu。
现在给出替换后的字符串,问替换前的字符串有几种可能,答案对
解析:很明显,如果给出的字符串中出现了 m 或者 w,那么这个字符串是不合法的,答案为
接下来分析连续 n 或者 u 的个数与答案的关系,以 n 为例:
如果有一段为 nn,那么这一段有 nn 或者 m;
如果有一段为 nnn,那么这一段有 nnn,mn,nm;
如果有一段为 nnnn,那么这一段有 nnnn,mnn,nmn,nnm,mm;
······;
然后我们把表列出来:
| ··· | ||||||
|---|---|---|---|---|---|---|
| 可能的情况数 | ··· |
发现什么没有(疯狂暗示)?
没错,Fibonacci 数列!!
所以我们直接先预处理 Fibonacci 数列,然后把每种情况的可能相乘即可。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
char s[101010];
int len,sum1,sum2;
int f[101010],mod=1e9+7;
long long ans=1;
int main()
{
scanf("%s",s+1);
len=strlen(s+1);
f[0]=1;
f[1]=1;
for(int i=2;i<=len;i++)
f[i]=(f[i-1]%mod+f[i-2]%mod)%mod;
for(int i=1;i<=len;i++)
{
if(s[i]=='m'||s[i]=='w')
{
printf("0");
return 0;
}
if(s[i]!='n'&&sum1)
{
ans*=f[sum1];
ans%=mod;
sum1=0;
}
if(s[i]!='u'&&sum2)
{
ans*=f[sum2];
ans%=mod;
sum2=0;
}
if(s[i]=='n')
{
sum1++;
continue;
}
if(s[i]=='u')
{
sum2++;
continue;
}
}
if(sum1)
ans=ans*f[sum1]%mod;
if(sum2)
ans=ans*f[sum2]%mod;
printf("%lld",ans%mod);
return 0;
}
D. Shichikuji and Power Grid
题意:有
解析:
原题:[USACO08OCT]打井Watering Hole。
对于建站的费用(即点权),我们可以建一个超级原点,把原点往每个点上连一条边权为
然后就是一个最小生成树的裸题了,这题不卡 Kruskal,直接开始码。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
long long n,x[2010],y[2010];
long long c[2010],k[2010];
long long cnt=0;
long long fa[2010],v,e,ans1[2010],ans2[2010][2];
long long ans;
struct node
{
long long next;
long long to;
long long num;
}edge[4001010];
bool cmp(node a,node b)
{
return a.num<b.num;
}
void add(long long from,long long to,long long num)
{
edge[++cnt].next=from;
edge[cnt].to=to;
edge[cnt].num=num;
}
long long dis(long long a,long long b)
{
return (k[a]+k[b])*(abs(x[a]-x[b])+abs(y[a]-y[b]));
}
long long getfa(long long x)
{
if(fa[x]==x)
return x;
return fa[x]=getfa(fa[x]);
}
int main()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++)
scanf("%lld%lld",&x[i],&y[i]);
for(int i=1;i<=n;i++)
scanf("%lld",&c[i]);
for(int i=1;i<=n;i++)
scanf("%lld",&k[i]);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
add(i,j,dis(i,j));
for(int i=1;i<=n;i++)
{
fa[i]=i;
add(0,i,c[i]);
}
sort(edge+1,edge+cnt+1,cmp);
for(int i=1;i<=cnt;i++)
{
int x=getfa(edge[i].next);
int y=getfa(edge[i].to);
if(x==y)
continue;
fa[x]=y;
ans+=edge[i].num;
if(edge[i].next==0)
{
ans1[++v]=edge[i].to;
continue;
}
if(edge[i].to==0)
{
ans1[++v]=edge[i].next;
continue;
}
if(edge[i].next!=0&&edge[i].to!=0)
{
ans2[++e][0]=edge[i].next;
ans2[e][1]=edge[i].to;
continue;
}
}
printf("%lld\n",ans);
printf("%lld\n",v);
for(int i=1;i<=v;i++)
printf("%lld ",ans1[i]);
printf("\n");
printf("%lld\n",e);
for(int i=1;i<=e;i++)
printf("%lld %lld\n",ans2[i][0],ans2[i][1]);
return 0;
}