题目大意:给你n根小棍,然后这样搭金字塔,每次搭最大的一个,求最多搭多少个
菜鸡做法:预处理下每一个金字塔需要多少根,我开到了1e5,这时候就已经是1e11的范围了,所以题目中的1e9完全可以。
然后upper_bound是个好东西,我暴力从n往前跑,不知道为什么会WA
每次求一下下标减1,直到n用完就行了
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e5+5;
ll a[N],b[N];
void init(){
for(int i=1;i<N;i++)b[i]=i;
for(int i=1;i<N;i++)b[i]+=b[i-1];
for(int i=1;i<N;i++)a[i]=2*b[i]+b[i-1];
// cout<<a[N-1];
}
int main(){
int t;
cin>>t;
init();
while(t--){
ll x,ans=0;
cin>>x;
if(x<2)cout<<0<<endl;
else if(x==2)cout<<1<<endl;
else {
while(x>=2){
int pos=upper_bound(a+1,a+N,x)-a;
pos--;
x-=a[pos];
ans++;
}
cout<<ans<<endl;
}
}
return 0;}
.
.
.
题意:转化成数学问题就是,有n个数,经过一个变化之后,询问是否变化之后的数是否完全不同。
菜鸡做法:那个变化是k+ak%n,转化成非负整数就是((k+a[i])%n+n)%n,这里dl们说涉及剩余系的概念,有兴趣的同学自己去查一下吧。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int a[N];
int main(){
int t;
cin>>t;
while(t--){
int n;
bool st[N],flag=true;
memset(st,false,sizeof st);
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++){
int x=((i+a[i])%n+n)%n;
if(st[x]){
cout<<"no"<<endl;
flag=false;
break;
}
st[x]=true;
}
if(flag)cout<<"yes"<<endl;
}
return 0;}