从某方面感觉比去年差多了,不知道为什么不能有题面了。
中午也不能有志愿者送盒饭。这三人一机属实难顶。
题目质量感觉还不错,感觉用作省赛恰到好处。
中文题面好评。
热身赛略,大家不到1个小时都AK了,感觉非常热身
话说最后一题撞了L大佬出过的原题?
(暴露了做题量过少的问题)
比赛开始。
开局七个题签的非常顺利,甚至一度rank 2
然后拉垮了,没有跟榜对象感觉还是不太熟悉
开了两个不可做的题,当时A觉得“数据完全随机”似乎有乱搞的可能,看了半天也没看明白。和一个K,想了一个小时也不知道那个人怎么可能赢钱。
过了一会队友开了一个M,开了半天wa了三发。我一看,是一个spfa的板子题,于是拍上去就过了。
当时已经被压两个题了。
然后跌跌撞撞写过去一个J的dp,
最后冲了一波B,也没写过去,就GG了
rank8跑路
夏老师:要是没进rank10提头来见
我:差点头就没了
先写下过完的题的做法吧,剩下题补完再更新
C.传染病统计
简单模拟,排个序扫一遍,只要差为2以内就记成一起,最后维护下最大最小值就行
#include
using namespace std;
int n;
bool allcap,cap1,capback;
int T;
int a[15];
int to[15];
int main()
{
cin>>T;
while(T--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
sort(a+1,a+n+1);
for(int i=1;i<=n;i++){
to[i]=i;
}
for(int i=1;i<n;i++){
if(a[i+1]-a[i]<=2) to[i]=i+1;
}
int mn=100,mx=1,cnt=0;
for(int i=1;i<=n;i++){
cnt++;
if(to[i]==i+1) continue;
else {
mn=min(mn,cnt);
mx=max(mx,cnt);
cnt=0;
}
}
printf("%d %d\n",mn,mx);
}
return 0;
}
D.阿强与网格
连搜索都不需要,比较下向下和向斜下走哪个更优就好了
#include
#include
#include
using namespace std;
int t;
long long n,m,x,y,ans;
int main(){
scanf("%d",&t);
while(t--){
scanf("%lld%lld%lld%lld",&n,&m,&x,&y);
if(m>n)swap(n,m);
if(m==1){
ans=(n-1)*x;
printf("%lld\n",ans);
continue;
}
if(y>=2*x)ans=(n+m-2)*x;
else if(y>=x){
ans=(m-1)*y+(n-m)*x;
}
else {
if((n-m)%2==0)ans=(n-1)*y;
else ans=(n-2)*y+x;
}
printf("%lld\n",ans);
}
return 0;
}
E.生活大爆炸
组合数基础
考虑从男的里面选i个,剩下从女生里选k-i个,乘起来,求和就行。
#include
#define ll __int128
using namespace std;
int n,m,t;
ll c(ll x,ll y){
if(y>x/2)y=x-y;
ll ret=1;
for(ll i=x;i>=x-y+1;i--)ret*=i;
for(ll i=1;i<=y;i++)ret/=i;
return ret;
}
int main()
{
cin>>n>>m>>t;
ll ans=0;
for(ll i=4;i<=min(n,t-1);i++){
if(t-i>m||t-i<1) continue;
ans+=c(n,i)*c(m,t-i);
}
int an[10000],cnt=0;
while(ans){
an[++cnt]=ans%10;
ans/=10;
}
for(int i=cnt;i>=1;i--){
printf("%d",an[i]);
}
return 0;
}
F.Capslock
简单模拟
#include
using namespace std;
char s[105];
int n;
bool allcap,cap1,capback;
char to(char x){
char ret=x;
if(ret>='A'&&ret<='Z'){
ret=ret-'A'+'a';
}
else{
ret=ret-'a'+'A';
}
return ret;
}
int main()
{
scanf("%s",s+1);
n=strlen(s+1);
int flag=0,sum=0;
for(int i=1;i<=n;i++){
if(s[i]>='A'&&s[i]<='Z'){
sum++;
}
}
if(sum==n) flag=1;
if(sum==n-1&&s[1]>='a'&&s[1]<='z') flag=1;
if(flag){
for(int i=1;i<=n;i++) s[i]=to(s[i]);
}
for(int i=1;i<=n;i++) putchar(s[i]);
return 0;
}
G.字节类型
会高精应该就秒了
Py的话可能都不需要
#include
using namespace std;
string a;
__int128 x=0;
int main()
{
cin>>a;
int len=a.size();
if(len>=20){
printf("BigInteger\n");
return 0;
}
for(int i=0;i<len;i++){
x=x*10+a[i]-'0';
}
if(x>9223372036854775807)printf("BigInteger\n");
else if(x>147483647)printf("long\n");
else if(x>32767)printf("int\n");
else if(x>127)printf("short\n");
else printf("byte\n");
return 0;
}
I.完美主义
线段树
维护区间的差分数组,最小值不小于0即可
#include
#define ll long long
#define N 300005
using namespace std;
ll a[N];ll b[N];int cnt=0;
int n,q;
struct tree{
ll a,b;
};tree t[N<<2];
void pushup(int v){
t[v].b=min(t[v<<1].b,t[v<<1|1].b);
}
void build(int l,int r,int v){
if(l==r){
//t[v].a=a[++cnt];
t[v].b=b[++cnt];
return;
}
int mid=(l+r)>>1;
build(l,mid,v<<1);
build(mid+1,r,v<<1|1);
pushup(v);
}
void update(int l,int r,int v,int x,ll val){
if(l==r){
t[v].b=val;
return;
}
int mid=(l+r)>>1;
if(x<=mid) update(l,mid,v<<1,x,val);
else update(mid+1,r,v<<1|1,x,val);
pushup(v);
}
ll query(int l,int r,int v,int ql,int qr){
if(ql<=l&&r<=qr){
return t[v].b;
}
int mid=(l+r)>>1;
ll ret=3e15;
if(ql<=mid) ret=min(ret,query(l,mid,v<<1,ql,qr));
if(mid+1<=qr) ret=min(ret,query(mid+1,r,v<<1|1,ql,qr));
return ret;
}
int main(){
cin>>n>>q;
a[0]=0;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
for(int i=1;i<=n;i++){
b[i]=a[i]-a[i-1];
}
build(1,n,1);
while(q--){
int opt;
scanf("%d",&opt);
if(opt==1){
int x;ll val;
scanf("%d%lld",&x,&val);
a[x]=val;
update(1,n,1,x,a[x]-a[x-1]);
if(x<n) update(1,n,1,x+1,a[x+1]-a[x]);
}
else{
int l,r;
scanf("%d%d",&l,&r);
ll ans=3e15;
if(l==r){
printf("Yes\n");
continue;
}
if(l>r){
printf("No\n");
continue;
}
ans=min(ans,query(1,n,1,l+1,r));
if(ans<0){
printf("No\n");
}
else printf("Yes\n");
}
}
return 0;
}
J.放棋子
基础dp吧
可以发现第i列和第 k ∗ n + i k*n+i k∗n+i列放的棋子个数是一样的
那么考虑二维dp,
dp[i][j]表示到第i个位置一共放了j个棋子的方案数
每个位置可以放(0~n)个,所以有一个 o ( n ∗ k ∗ n ) o(n*k*n) o(n∗k∗n)的dp方案
第i列乘个快速幂即可,组合数和快速幂都可以预处理成 o ( 1 ) o(1) o(1)
#include
#define ll long long
using namespace std;
const long long MOD=1000000007;
long long n,m,t;
long long dp[105][10050],c[105][105],d[2][105][105],inv[105];
long long C(int xx,int yy)
{
if(yy==0)return 1;
long long ans=1;
for(int i=xx;i>=xx-yy+1;i--) ans=ans*i%MOD;
for(int j=1;j<=yy;j++) ans=ans*inv[j]%MOD;
return ans;
}
long long p(long long xx,long long yy)
{
long long k=yy,x=xx;
ll ret=1;
while(k){
if(k&1)ret=ret*x%MOD;
x=x*x%MOD;
k>>=1;
}
return ret;
}
int main()
{
scanf("%lld%lld%lld",&n,&m,&t);
inv[1]=1;
for(int i=2;i<=100;i++)inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD;
memset(dp,0,sizeof(dp));
for(int j=0;j<=100;j++)
c[n][j]=C(n,j);
for(int i=0;i<=100;i++){
d[0][n][i]=p(c[n][i],m/n);
d[1][n][i]=p(c[n][i],m/n+1);
}
dp[0][0]=1;
if(t>n*n/2)t=n*n-t;
for(int i=0;i<n;i++){
for(int j=0;j<=min(t,i*n);j++){
for(int k=0;k<=n;k++){//printf("%d %d %d!!!\n",i,j,k);
if(j+k>t) continue;
ll now;
if(i+1<=m%n)now=d[1][n][k];
else now=d[0][n][k];
dp[i+1][j+k]=(dp[i+1][j+k]+dp[i][j]*now%MOD)%MOD;
}
}
}
// for(int i=1;i<=n;i++) {
// for(int j=0;j<=t;j++) printf("%d ",dp[i][j]);
// printf("\n");
// }
printf("%lld\n",dp[n][t]);
return 0;
}
L.神奇的回答
签到,差点一血
#include
using namespace std;
int main()
{
int t;
scanf("%d",&t);
int a;
while(t--) {
scanf("%d",&a);
if(a>18) printf("18\n");
else printf("%d\n",a);
}
return 0;
}
M.比赛!
spfa裸板子,一个点入队n次判不可能
#include
#define ll long long
using namespace std;
int n,cnt=0;
char x,y,z;
int sum=0,head[505],tme[505];
char s[505];
int dis[505],in[505];
bool vis[505];
map<char,int>mp;
struct paper{
int to,nxt;
};
paper edge[1050];
void add(int aa,int bb)
{
// cout<
in[bb]++;
edge[++sum].to=bb; edge[sum].nxt=head[aa]; head[aa]=sum;
}
/*void bfs(int pos,int dp) {
queue q;
//printf("%d %d\n",pos,dp);
//vis[pos]=1;
dep[pos]=max(dep[pos],dp);
for(int i=head[pos];i!=-1;i=edge[i].nxt) {
int tt=edge[i].to;
dfs(tt,dp+1);
}
// vis[pos]=0;
}*/
bool noans(int pos) {
//printf("%d --- %d\n",pos,vis[pos]);
if(vis[pos]) return 1;
vis[pos]=1;
for(int i=head[pos];i!=-1;i=edge[i].nxt) {
int tt=edge[i].to;
if(noans(tt)) return 1;
}
vis[pos]=0;
return 0;
}
/*bool noans(int pos){
if(vis[pos])return 1;
int ret=0;
vis[pos]=1;
for(int i=0;i
void spfa(){
memset(tme,0,sizeof(tme));
memset(vis,0,sizeof(vis));
for(int i=1;i<=cnt;i++) dis[i]=-1e9;
queue<int>q;
q.push(0);dis[0]=0;vis[0]=1;
while(!q.empty()){
int u=q.front();
q.pop();vis[u]=0;
for(int i=head[u];i!=-1;i=edge[i].nxt){
int v=edge[i].to;
// printf("%d %d\n",u,v);
if(dis[v]<dis[u]+1){
dis[v]=dis[u]+1;
if(!vis[v]){
q.push(v);
vis[v]=1;
tme[v]++;
if(tme[v]>cnt) {
printf("No Answer\n");
exit(0);
}
}
}
}
}
/*for(int i=1;i<=cnt;i++) {
printf("%d ",dis[i]);
}
printf("\n");*/
}
bool cmp(char xx,char yy) {
return dis[mp[xx]]<dis[mp[yy]];
}
int main(){
memset(in,0,sizeof(in));
memset(vis,0,sizeof(vis));
// memset(vis,0,sizeof(dep));
for(int i=0;i<=500;i++){
head[i]=-1;
}
scanf("%d\n",&n);
mp.clear();
for(int i=1;i<=n;i++){
scanf("%c:%c%c",&y,&x,&z);
if(i<n) scanf("\n");
if(x==y||x==z||y==z){
printf("No Answer\n");
return 0;
}
if(!mp[x]){
mp[x]=++cnt;
s[cnt]=x;
}
if(!mp[y]){
mp[y]=++cnt;
s[cnt]=y;
}
if(!mp[z]){
mp[z]=++cnt;
s[cnt]=z;
}
add(mp[x],mp[y]);
add(mp[y],mp[z]);
}
bool flag=0;
for(int i=1;i<=cnt;i++) {
if(in[i]==0){
flag=1;
add(0,i);
}
}
if(flag==0) {
printf("No Answer\n");
return 0;
}
/*if(noans(0)){
printf("No Answer\n");
return 0;
}
else*/ {
memset(vis,0,sizeof(vis));
spfa();
sort(s+1,s+1+cnt,cmp);
for(int i=1;i<=cnt;i++) {
printf("%c",s[i]);
}
}
}/*
3
A:bd
A:db
b:AC
4
2:13
3:24
4:35
5:46
5
2:13
3:24
4:35
5:46
6:71
*/
自己就算有信心最好也大家一起看下再上机。感觉还是尽量把对应的题塞给负责该知识点的队友。
尽量不要all in没人过的题(执着一血是坏文明)
最后桂林加油!
来补一发题
H.制造游戏币
场上没看到,开了不可做的题。
发现这个题就是个裸背包题
考虑题目限制一定是若干条链必选成递增序列,先把他处理成0,1,2,…,的必选模式,然后把每个点的价值更新成选他必须付出的代价和,就是裸背包
//by_ileln
//#define LOCAL
#include
using namespace std;
#define IL inline
#define ll long long
#define pii pair<int,int>
#define N 1000005
#define M(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define cinio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define lowbit(x) x & -x
#define dbg(x) cout << #x << " = " << x << endl
ll mod=1e9+7;
int head[N];struct edge{int to,next;};edge e[N<<1];
int cmt=0;int T;
int n,m,k;
int tree[N<<2];void Add(int x,int k){while(x<=n){tree[x]+=k;x+=lowbit(x);}}
int Sum(int x){int ans=0;while(x!=0){ans+=tree[x];x-=lowbit(x);}return ans;}
void add(int u,int v){e[++cmt].to=v;e[cmt].next=head[u];head[u]=cmt;}
template<typename Tp> IL void read(Tp &x){x=0;int f=1;char ch=getchar();while(!isdigit(ch)){
if(ch == '-')f=-1;ch=getchar();}while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}x*=f;}
int buf[42];
template<typename Tp> IL void write(Tp x){int p=0;if(x<0){putchar('-'); x=-x;}if(x==0)
{putchar('0');return;}while(x){buf[++p] = x % 10;x /= 10;}for(int i=p;i;i--) putchar('0'+buf[i]);}
ll quick(ll a,ll b){ll ret=1;ll now=a;while(b){if(b&1){ret*=now;ret%=mod;}now*=now;now%=mod;b>>=1;}return ret;}
ll Inv(ll b){if(b==1)return 1;return(mod-mod/b)*Inv(mod%b)%mod;}
ll fac[N],inv[N];void getc(){fac[0]=inv[0]=1;for(int i=1;i<n;i++)fac[i]=fac[i-1]*i%mod;
inv[n-1]=quick(fac[n-1],mod-2);for(int i=n-2;i;i--)inv[i]=inv[i+1]*(i+1)%mod;}
ll c(int a,int b){return fac[n]*inv[m]%mod*inv[n-m]%mod;}
ll C(ll a,ll b,ll p){if(b>a)return 0;ll res=1;for(ll i=1,j=a;i<=b;i++,j--){res=res*j%p;res=res*quick(i,mod-2)%p;}return res;}
ll lucas(ll n, ll m,ll p){return m?lucas(n/p,m/p,p)*C(n%p,m%p,p)%p:1;}
/*int fa[N][22];int Fa(int i,int k){for(int x=0;x<=int(log2(k));x++)if((1<
/*int B[N],p[N],pcnt=0;void getPrime(int n){B[1]=0;for(int i=2;i<=n;i++){if(!B[i]) p[++pcnt]=i;
for(int j=1;j<=pcnt&&i*p[j]<=n;j++){B[i*p[j]]=1;if(i%p[j]==0)break;}}}*/
map<int,int>mp;
int a[N],vis[N];
ll dp[N];
void dfs(int u){
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
a[v]+=a[u];
dfs(v);
}
if(head[u]) k-=a[u];
}
int main(){
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif
T=1;
while(T--){
read(n);read(m);read(k);
for(int i=1;i<=n;i++){
read(a[i]);
}
for(int i=1;i<=m;i++){
int u,v;read(u);read(v);
add(u,v);vis[v]=1;
}
for(int i=1;i<=n;i++){
if(!vis[i]) dfs(i);
}
dp[0]=1;
for(int i=1;i<=n;i++){
for(int j=a[i];j<=k;j++){
dp[j]=(dp[j-a[i]]+dp[j])%mod;
}
}
write(dp[k]);
}
return 0;
}