CF1091
CF1091A
水题。去个 \(\min\) 即可。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
const int N=4e6+5;
const int M=1e5+5;
const int mod=1e5+3;
inl int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return x*f;
}
inl void write(int x){
if(x<0){x=-x;putchar('-');}
if(x>9)write(x/10);
putchar(x%10+'0');
}
inl void writei(int x){write(x);putchar(' ');}
inl void writel(int x){write(x);putchar('\n');}
int y,b,r;
signed main(){
y=read();b=read()-1;r=read()-2;
writel(min(y,min(b,r))*3+3);
return 0;
}
CF1091B
正解:把所有数加起来除以 \(n\)就是答案()
我的zz做法:枚举向量,求出加上第一个点后终点坐标,再对于其它点看向量是否存在
复杂度 \(O(n^2\log n)\) 稳居最劣解()
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
const int N=1e5+5;
const int M=1e5+5;
const int mod=1e5+3;
inl int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return x*f;
}
inl void write(int x){
if(x<0){x=-x;putchar('-');}
if(x>9)write(x/10);
putchar(x%10+'0');
}
inl void writei(int x){write(x);putchar(' ');}
inl void writel(int x){write(x);putchar('\n');}
int n,x[N],y[N],a[N],b[N];
map<pair<int,int>,int>mp;
signed main(){
n=read();
for(int i=1;i<=n;i++)x[i]=read(),y[i]=read();
for(int i=1;i<=n;i++)a[i]=read(),b[i]=read();
for(int i=1;i<=n;i++){
int tx=x[1]+a[i],ty=y[1]+b[i];
mp.clear();int flag=0;
for(int i=1;i<=n;i++)mp[{a[i],b[i]}]++;
for(int i=2;i<=n;i++){
int aa=tx-x[i],bb=ty-y[i];
if(!mp[{aa,bb}]){flag=1;break;}
mp[{aa,bb}]--;
}
if(flag)continue;
writei(tx);writel(ty);
}
return 0;
}
CF1091C
手玩样例会发现一件事:对于 \(n\) 的因数 可能会跳过几个同学 其他情况都和1一样 每个人都跳
每种情况的答案是一个等差数列 可以 \(O(1)\) 求出结果
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define int ll
const int N=1e5+5;
const int M=1e5+5;
const int mod=1e5+3;
inl int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return x*f;
}
inl void write(int x){
if(x<0){x=-x;putchar('-');}
if(x>9)write(x/10);
putchar(x%10+'0');
}
inl void writei(int x){write(x);putchar(' ');}
inl void writel(int x){write(x);putchar('\n');}
int n;
vector<int>v;
signed main(){
n=read();
for(int i=1;i*i<=n;i++){
if(n%i)continue;
v.push_back(i);
if(i*i^n)v.push_back(n/i);
}
sort(v.begin(),v.end(),greater<int>());
for(auto i:v)writei((n-i+2)*n/2/i);
return 0;
}
CF1091D
题意:
给定整数 \(n\) ,把所有 \(1\) 到 \(n\) 的排列按字典序拼成长为 \(n\)·\(n!\) 的序列。
求出有多少个长度为 \(n\) 、和为 \(n(n+1)/2\) 的连续子列,答案对素数 \(998244353\) 取模。
solution:
首先,长度为 \(n\) 、和为 \(n(n+1)/2\) 的连续子列 很显然就是满足 \(n\) 个数中 \(1...n\) 各出现一次的序列(依据题意不会出现其他情况)
那么我们考虑 \(n=3\) 的情况:
\[\underline{123}\ \underline{132}\ \underline{213}\ \underline{231}\ \underline{312}\ \underline{321}
\]
\[1\underline{23\ 1}32\ 2\underline{13\ 2}31\ 3\underline{12\ 3}21
\]
我们可以按第一位是否相同 把序列分成 \(n\) 段
那么求的就是每一段内 以 \(1、2、3...n\) 每一位为开头 接下来 \(n\) 个数满足条件的个数 最后答案乘 \(n\)
然后我们可以发现 以 \(1、3...n\) 为开头的答案与 \(f_{i-1}\) 相同(看做去掉每个数开头的1)
第二位开头的情况 发现除了最后一个位置越界 其他都满足 答案 \((n-1)!-1\)
递推式 \(f_i=i\times(f_{i-1}+(i-1)!-1)=i\times f_{i-1}+i!-i\)
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define int ll
const int N=1e6+5;
const int M=1e5+5;
const int mod=998244353;
inl int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return x*f;
}
inl void write(int x){
if(x<0){x=-x;putchar('-');}
if(x>9)write(x/10);
putchar(x%10+'0');
}
inl void writei(int x){write(x);putchar(' ');}
inl void writel(int x){write(x);putchar('\n');}
int n,f[N],fac;
signed main(){
n=read();
f[1]=1;fac=1;
for(int i=2;i<=n;i++)f[i]=(i*f[i-1]%mod+(fac=fac*i%mod)-i+mod)%mod;
writel(f[n]);
return 0;
}

浙公网安备 33010602011771号