B
找规律
可以想象为 \\ 这样斜向右的摆放,
每加一层,相当于把 最右边的 \ 向右平移复制一次,
再加上最顶部的3个
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAX_N=3e4+5;
long long f[MAX_N];
int main()
{
f[1]=2; ll x=5;
long long mx=30000;
for(int i=2;i<=mx;i++){
f[i]=f[i-1]+x;
x+=3;
}
//cout<<f[mx]<<endl;
int t; cin>>t;
while(t--){
int n; scanf("%d",&n);
int ans=0;
for(int i=mx;i>=1;i--){
while(n>=f[i]) n-=f[i],ans++;
}
printf("%d\n",ans);
}
return 0;
}
C
思路,由于每 n个数的移动方式相同,我们可以考虑缩小范围,判断在1~n范围内是否冲突
只要在1~ n范围内不冲突,n+1~2n范围也不冲突,
进而,所有范围都不冲突
1 ~ n范围移动后会到其他范围,而再+n或-n可以回到1~n范围,(也就是取模)
移动后±n相当于移动前的数±n,转化为其他范围的数移动到1~n,这样就可以判断是否冲突了
#include<bits/stdc++.h>
using namespace std;
const int MAX_N=2e5+5;
int a[MAX_N],cnt[MAX_N];
int main()
{
int t,n; scanf("%d",&t);
while(t--){
scanf("%d",&n); for(int i=0;i<=n;i++) cnt[i]=0;
int ok=1;
for(int i=0;i<=n-1;i++){
scanf("%d",&a[i]);
int x=(i+a[i])%n;
x=(x+n)%n;
cnt[x]++;
if(cnt[x]>=2) ok=0;
}
if(ok) puts("YES");
else puts("NO");
}
return 0;
}