B 一生之敌
2*a*(a+1)^2 = b^2 因为要求b 所以先开个根号把b求出来 => b = sqrt(2*a) * (a+1)因为b是整数a也是整数, 而等式中出现了根号2,所以要变换一下把根号2去掉令 sqrt(a) = sqrt(2*x) 其中2*x为整数 ,得到等式b = 2*x*(2*x*x+1) = 4*x*x*x + 2*x二分x得到答案其中因为n的范围在[1,1e19]内,而1e19是比long long 的范围大的考虑了使用double 不过有精度误差,还用Java写了一次,还是错,,结束看了别人的代码才想起来还有 unsigned long long 这一类型~
#include <iostream> #include <string> #include <string.h> using namespace std; #define ULL unsigned long long ULL n; int main() { int T; scanf("%d",&T); while(T--){ scanf("%llu",&n); ULL l=0,r=1400000,mid; while(l<r){ mid = (l+r)>>1; if(4*mid*mid*mid + 2*mid >= n) r = mid; else l = mid+1; } printf("%llu\n",2*r*(2*r*r+1)); } }
C 寻找zcmu
找到z后面第一个c再继续找c下面第一个m再找m下面第一个u,u的位置减去z的位置-3就是该zcmu连续要删除的字母个数
先从后往前预处理一下,求出每个z后面的第一个c,每个c后面的第一个m,每个m后面的第一个u,然后遍历一遍就得到答案了
#include <iostream> #include <string.h> #include <stdio.h> using namespace std; #define LL long long const int N = 1e5 + 10; int T,n,m,nt[N],len,ans; char s[N]; void slove(char a,char b){ for(int i = len-1,now = -1;i>=0;i--){ if(s[i] == a) nt[i] = now; else if(s[i] == b) now = i; } } int main() { while(scanf("%s",s)!=EOF){ memset(nt,-1,sizeof nt); len = strlen(s); ans = N; slove('m','u'); slove('c','m'); slove('z','c'); for(int i=0;i<len;i++){ if(s[i]=='z'){ int now = i; for(int j=0;j<3&&~now;j++){ now = nt[now]; } if(now==-1) continue; ans = min(ans, now-i-3); } } printf("%d\n",ans==N?-1:ans); } return 0; }
D CC的神奇背包
贪心,将所有物品分为放了之后包剩余容量变大和变小的两种,然后分别按体积从小到大排序,然后先放变大的,再放变小的,每次放置更新包的体积,若有一次不能再放入某一物品,则输出no
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define LL long long const int N = 1e5 + 10; int T,n,m,x,y,z; struct node{ int a,b; }a[N],b[N]; bool cmp(node a,node b){ return a.a<b.a; } int main() { scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); int cnt1 = 0, cnt2 = 0; for(int i=0;i<n;i++){ scanf("%d%d",&x,&y); if(x<=m&&y-x>=0){ m += y-x; }else{ if(y-x>=0) { a[cnt1].a = x; a[cnt1++].b =y; }else { b[cnt2].a = x; b[cnt2++].b =y; } } } int flag = 1; sort(a,a+cnt1,cmp); sort(b,b+cnt2,cmp); for(int i=0;i<cnt1;i++){ if(m<a[i].a){ flag = 0; break; }else{ m -= a[i].a - a[i].b; } } if(flag){ for(int i=0;i<cnt2;i++){ if(m<b[i].a){ flag = 0; break; }else{ m -= b[i].a - b[i].b; } } } if(!flag){ printf("no\n"); }else{ printf("yes\n"); } } return 0; }
E Pizza
贪心,分为n块质量为1的,答案就是k,签到题 ,数据超int
#include <iostream> #include <string.h> #include <stdio.h> using namespace std; #define LL long long LL T,n,m; int main() { scanf("%lld",&T); while(T--){ scanf("%lld%lld",&n,&m); printf("%lld\n",m); } return 0; }
G 特产
签到题,两数相减就是答案
#include <iostream> #include <stdio.h> #include <string.h> using namespace std; #define LL long long int T; LL n,m; int main() { scanf("%d",&T); while(T--){ scanf("%lld%lld",&n,&m); printf("%lld\n",m-n); } return 0; }
H 剪纸
题意就是有一个大小为n*n的正方形,将其一刀剪成两半,且两半要完全相同,求共能剪出多少种不同的形状(旋转后同样不同)
和今年浙江的蓝桥省赛有一题是一样的,因为要完全相同,所以一定是中心对称图形,以中心点为起点DFS求出所有的剪的线路,两边同时向外走,走的方向要想反,碰到边界就结束了,此时方案数加一,然后最终答案要旋转后也不能相同,所以最终答案为所有线路方案/4
#include <iostream> #include <string.h> #include <stdio.h> using namespace std; int T,n; int dir[4][2] = {0,1,1,0,0,-1,-1,0}; int rdir[4][2] = {0,-1,-1,0,0,1,1,0}; int vis[15][15],ans; bool check(int x,int y){ if(x<0||x>n||y<0||y>n||vis[x][y]) return false; return true; } void dfs(int x1,int y1,int x2,int y2){ if(x1==0||x1==n||y1==0||y1==n){ ans++; return; } vis[x1][y1] = vis[x2][y2] = 1; for(int i=0;i<4;i++){ int X1 = x1 + dir[i][0]; int Y1 = y1 + dir[i][1]; int X2 = x2 + rdir[i][0]; int Y2 = y2 + rdir[i][1]; if(!check(X1, Y1)||!check(X2, Y2)) continue; dfs(X1,Y1,X2,Y2); } vis[x1][y1] = vis[x2][y2] = 0; } int main() { scanf("%d",&T); while(T--){ scanf("%d",&n); if(n%2){ printf("0\n"); continue; } ans = 0; dfs(n/2,n/2,n/2,n/2); printf("%d\n",ans/4); } return 0; }