题目链接:https://codeforces.com/contest/1371
集训day1,整个6月都在预习备考,咕了一个多月之后的第一套题。居然只A了3题,然后补了3题。
程序开头,后面不再重复
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define FOR(i,l,r) for(int i=l;i<=r;i++)
#define ROF(i,l,r) for(int i=l;i>=r;i--)
#define pb(x) push_back(x)
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rr(x,y) read(x);read(y)
#define rrr(x,y,z) read(x);read(y);read(z)
#define sss(str) scanf("%s",str+1)
#define ssf(x) scanf("%lf",&x)
#define aLL(x) x.begin(),x.end()
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=2e5+5;
const int M=2e3+5;
const int INF=2e9;
const int sz=15;
const int mod=1e9+7;
const double eps = 1e-8;
const double pi= acos(-1);
template<class T>
inline void read(T &x)
{
char c;x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
这题不难看出,2个拼最划算 ,最大的和最小的拼 ,然后次大的和次小的 …
int n,m;
char str[N];
int f[N];
int main()
{
int t;
r(t);
while(t--){
r(n);
int ans=n/2;
if(n&1) ans++;
cout<<ans<<endl;
}
return 0;
}
设当前的宽为x,若n>=x 则只有一横条 (即只有一种)
若n
int main()
{
int t;
r(t);
while(t--){
rr(n,m);
LL ans=0;
if(n<=m){
ans+=1ll*(n-1)*n/2; //1 - n-1
ans++;
}
else{
ans+=1ll*(m+1)*m/2;
}
cout<<ans<<endl;
}
return 0;
}
这题描述很复杂,也确实把我绕晕了 ,其实说的就是
第一种人:先选多的那种,如果两种相等则选后者
第二种人:先选少的那种,如果两种相等则选前者
现在假设有a 和 b,其中a>b,如果我们先排第二种人,那么b直接就选没了,显然很难满足。所以我们先排第一种人。直到 a = b时,这时选第一种人 那么就是a和b交替减1;选第二种人还是直接选没了。不难发现,不管怎样b都是选少的那方,所以我们不妨先把第二种人排完,然后排第一种人。
int main()
{
int t;
r(t);
while(t--){
LL a,b,c,d;
rr(a,b); rr(c,d);
if(a<b) swap(a,b);
// if((a==0&&c!=0)||(b==0&&d!=0)){
// cout<<"NO\n";
// continue;
// }
LL dif=a-b;
if(c>=dif){
c-=dif;
if(b>=d&&2*b>=c+d) cout<<"YES\n";
else cout<<"NO\n";
}
else{
if(b>=d) cout<<"YES\n";
else cout<<"NO\n";
}
}
return 0;
}
每次选一条正斜线,就可以保证每次增加的都是均匀的
比如先选红线为1,再绿线,再蓝线。每一条线经过的点 都是增加不同的行和列,所以均匀。
这样不难看出,当选的是整条线时,完全均匀,ans=0,不完整时,最多也只差1,ans=2
int g[500][500];
int main()
{
int t;
r(t);
while(t--){
rr(n,m);
memset(g,0,sizeof g);
int x=1,y=1;
int tmp=m;
while(tmp--){
g[x][y]=1;
x++; y=y%n+1;
if(x==n+1){
x=1;
y=y%n+1;
}
}
if(m%n==0) cout<<0<<endl;
else cout<<2<<endl;
FOR(i,1,n){
FOR(j,1,n) cout<<g[i][j];
cout<<endl;
}
}
return 0;
}
这题可以去看题解,我也是看官方题解写出来的https://codeforces.com/blog/entry/79624
首先要明白这个式子
其中bi表示的是整个序列中小于等于i的数的个数
当我们选第一个数时,肯定是要选小于等于x的数,即bx
第二个数,肯定要小于等于x+1,即bx+1,但是之前选走了一个数,所以只有bx+1 - 1种
以此类推,可得上式
设max为整个序列的最大值
当 x + n − 1 < m a x x+n-1
当 x ≥ m a x x\geq max x≥max时,随便怎么选都可以,即f(x)=n!,也不满足
其他情况就是 m a x − n + 1 ≤ x < m a x max-n+1 \leq x
我们只需要满足
范围不超过2e5,所以我们可以直接记录i-bi的值,然后直接map找即可
int n,m;
char str[N];
int f[N];
unordered_map<int,int> mm;
int main()
{
rr(n,m);
FOR(i,1,n){
r(f[i]);
}
sort(f+1,f+n+1);
FOR(i,f[n]-n+1,f[n]+n-2){
mm[i]=(i%m-(upper_bound(f+1,f+n+1,i)-f-1)%m+m)%m;
}
unordered_map<int,int> mmm;
int st=max(0,f[n]-n+1);
FOR(i,1,n-1){
int now=st+i-1;
mmm[mm[now]]++;
}
vector<int> ans;
FOR(i,st,f[n]-1){
mmm[mm[i+n-1]]++;
if(mmm.count(i%m)&&mmm[i%m]>0){
// cout<
}
else{
ans.pb(i);
}
mmm[mm[i]]--;
}
cout<<ans.size()<<endl;
for(int x:ans){
cout<<x<<' ';
}
cout<<endl;
return 0;
}