• OI-Contest 荣耀徽章

    该用户太菜了,一个徽章也没有 (´・ω・`)
  • 个人简介

    /* 30分: 某种神秘的暴力

    60分: 枚举两个班各分多少糖果,判断是否符合要求

    100分: 推公式 显然n%(x+y)==0时成立 假设一班小朋友每人a颗糖果,二班小朋友每人a+1颗糖果 a*x+(a+1)y=n a(x+y)+y=n n%(x+y)==y 同理得n%(x+y)==x */ #include<bits/stdc++.h> using namespace std; int main(){ freopen("candy.in","r",stdin); freopen("candy.out","w",stdout); int t; scanf("%d",&t); while(t--){ int n,x,y; scanf("%d%d%d",&n,&x,&y); if(n%(x+y)==0){ printf("Yes\n"); continue; } if(n%(x+y)==x){ printf("Yes\n"); continue; } if(n%(x+y)==y){ printf("Yes\n"); continue; } printf("No\n"); } return 0; }

    /* 30分: 暴搜

    60分: 二进制枚举

    100分: 从小到大选数 注意到8+5=13 重要性质:若x在集合B中,x+13也可以在集合B中 证明: x在集合B中,则x+5和x+8一定不在集合B中 因此x+13能在集合B中

    把数分为每13个一组 暴搜n小于等于13的情况 并处理n=13时,前k(k<13)个数里能选几个 输出n/13*ans[13]+c[n%13] */ #include<bits/stdc++.h> using namespace std; int pan[20],c[20],ans[20]; void dfs(int depth,int num){ if(depth>ans[num]){ ans[num]=depth; if(num==13){ for(int i=1;i<=num;i++){ if(pan[i]) c[i]=1; else c[i]=0; c[i]+=c[i-1]; } } } for(int i=1;i<=num;i++){ if(pan[i]==0){ if(i-5>0&&pan[i-5]==1) continue; if(i+5<=13&&pan[i+5]==1) continue; if(i-8>0&&pan[i-8]==1) continue; if(i+8<=13&&pan[i+8]==1) continue; pan[i]=1; dfs(depth+1,num); pan[i]=0; } } return ; }

    int main(){ freopen("set.in","r",stdin); freopen("set.out","w",stdout); for(int i=1;i<=13;i++) dfs(0,i); int t; scanf("%d",&t); while(t--){ int n; scanf("%d",&n); if(n<=13) printf("%d\n",ans[n]); else printf("%d\n",n/13*ans[13]+c[n%13]); } return 0; }

    /* 30分: 暴搜拿不到,需要二进制枚举

    60分: 某种神秘的O(n^4)做法

    100分: 区间DP dp[i][j]表示把[i,j]这个区间的狼全打败所承受的最小伤害 枚举中间点k,dp[i][j]=min(dp[i][k-1]+dp[k+1][j]+a[k]+b[i-1]+b[j+1]) 注意每组数据结束后要清空ab数组 */ #include<bits/stdc++.h> using namespace std; const int N=210; const int inf=1e9+7; int a[N],b[N],dp[N][N]; int main(){ freopen("wolf.in","r",stdin); freopen("wolf.out","w",stdout); int t; scanf("%d",&t); for(int u=1;u<=t;u++){ int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) scanf("%d",&b[i]);

    	for(int i=1;i<=n;i++)
    		for(int j=i;j<=n;j++)
    			dp[i][j]=inf;
    
    	for(int len=1;len<=n;len++){
    		for(int i=1;i+len-1<=n;i++){
    			int j=i+len-1;
    			for(int k=i;k<=j;k++){
    				dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j]+a[k]+b[i-1]+b[j+1]);	//b[n+1] 
    			}
    		}
    	}
    	printf("Case #%d: %d\n",u,dp[1][n]);
    	
    	for(int i=1;i<=n;i++){
    		a[i]=0;
    		b[i]=0;
    	}
    }
    return 0;
    

    }

    /* 30分: 暴搜

    60分: 某种神秘的特殊情况

    100分: 考虑为何会出现多种方案 在记录一个数x时,可以选择删掉x左边的数,也可以删掉x右边的数 什么时候可以删掉左边的数? 按顺序记录数时,一个数只要被记录到b中,就没有用了 因此,左边的数没有出现在b中,或者左边的数在b中的顺序在x之前 此时可以删掉左边的数 右边的数同理 在a中记录b的数的出现顺序即可

    左右均可删,答案*2 左右一可删,答案不变 左右不可删,答案为0 / #include<bits/stdc++.h> using namespace std; const int N=200010; const int mod=998244353; const int inf=1e9+7; int a[N],b[N],num[N],pos[N]; int main(){ freopen("operation.in","r",stdin); freopen("operation.out","w",stdout); int t; scanf("%d",&t); while(t--){ int n,k; scanf("%d%d",&n,&k); num[0]=inf; num[n+1]=inf; for(int i=1;i<=n;i++){ num[i]=0; pos[i]=0; } for(int i=1;i<=n;i++){ scanf("%d",&a[i]); pos[a[i]]=i; } for(int i=1;i<=k;i++){ scanf("%d",&b[i]); num[pos[b[i]]]=i; } int ans=1; for(int i=1;i<=k;i++){ if(num[pos[b[i]]-1]>num[pos[b[i]]]&&num[pos[b[i]]+1]>num[pos[b[i]]]){ ans=0; } if(num[pos[b[i]]-1]<num[pos[b[i]]]&&num[pos[b[i]]+1]<num[pos[b[i]]]){ ans=2; ans%=mod; } } printf("%d\n",ans); } return 0; }

  • 证书

    该用户太菜了,一本证书也没有 (´・ω・`)
  • AC题目

Problem Tags

动态规划
9
二分
8
贪心
6
前缀和
5
gcd
5
计算
5
5
数学
5
其他
4
dfs
4
模拟
4
快速幂
4
差分
4
DFS枚举
4
排序
3
map
3
递归
3
组合数学
3
双指针
3
3