8月11日 集训测试

    xiaoxiao2025-10-20  3

    B

    题目链接

    http://acm.hust.edu.cn/vjudge/problem/24840

    题意

    给出一个天枰的文字描述,问最少修改多少次可以使天枰的所有支点都是平衡的。

    题解

    找一个基准(depth*weigh),把其他所有的重量的基准都修改为这个值,那么只要这个基准的出现次数最多,那么修改的次数也就越少。sum-基准次数。

    代码

    #include<iostream> #include<queue> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<string> #include<cctype> #include<algorithm> #include<vector> #include<map> using namespace std; int main() { int t; scanf("%d",&t); while(t--) { string st; cin>>st; int n=st.size(); int cnt1=0,cnt2=0; map<long long,int>num; int cnt3=0; for(int i=0;i<n;i++) { if(st[i]=='['){cnt1++;cnt2++;} //出现一个'['深度就+1 else if(isdigit(st[i])) //只要是数字就开始“基准”处理 { long long numm=st[i]-'0'; i++; while(isdigit(st[i])){ numm=numm*10+st[i]-'0'; i++; if(i>=n){break;} } i--; long long aa=1; for(int j=0;j<cnt1;j++)aa*=2; numm*=aa; num[numm]++; cnt3++; } else if(st[i]==']')cnt1--; //出现一个']'深度-1 } map<long long,int>::iterator it=num.begin();//用一个map映射基准出现的次数,最后找到出现次数最多的基准。 int ans=-1; for(;it!=num.end();it++) { ans=max(ans,it->second); } if(cnt2==0)printf("0\n"); else printf("%d\n",cnt3-ans); } return 0; }

    C

    题目链接

    http://acm.hust.edu.cn/vjudge/problem/22883

    题意

    切披萨,问n刀下去,披萨可以被切成几块。

    题解

    ans=1+((n+1)*n)/2;

    D

    题目链接

    http://acm.hdu.edu.cn/showproblem.php?pid=4334

    题意

    给出5个数的集合,问能否从每个集合中选出一个数,使5个数之后等于0。

    题解

    先把前两个集合的数的和依次求出来,得到新集合n1,然后同样处理第三第四个集合得到新集合n2,遍历第五个集合中的每个元素x,n=n1+x,二分查找在n2集合中是否存在n的相反数。

    代码

    #include<iostream> #include<queue> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<string> #include<cctype> #include<algorithm> #include<vector> using namespace std; long long a[7][300]; int main() { int t; scanf("%d",&t); while(t--) { for(int i=0;i<7;i++) for(int j=0;j<300;j++)a[i][j]=0; int n; scanf("%d",&n); for(int i=0;i<5;i++) for(int j=0;j<n;j++)scanf("%lld",&a[i][j]); vector<long long>s1; vector<long long>s2; for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { long long t=a[0][i]+a[1][j];s1.push_back(t); } } //处理第一第二个集合 for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { long long t=a[3][i]+a[4][j];s2.push_back(t); } } //处理第三第四个集合 sort(s1.begin(),s1.end()); //排序后二分查找 sort(s2.begin(),s2.end()); int ok=0; for(int i=0;i<n;i++) { for(int j=0;j<s1.size();j++) { long long t=a[2][i]+s1[j]; int op=lower_bound(s2.begin(),s2.end(),-t)-s2.begin();//二分查找 if(s2[op]+t==0){ok=1;break;} } if(ok==1)break; } if(ok==1)printf("Yes\n"); else printf("No\n"); } return 0; }

    F

    题目链接

    http://acm.hdu.edu.cn/showproblem.php?pid=4346

    题意

    只要存在i位置为R,j位置也为R,并且(i+j)/2位置为G,那么这条路就是美丽的,问最多可以构造出多少条美丽的路。

    题解

    正面构造感觉特别难,不能把所有情况按某种思路一次找出来。所有就反着来了,美丽的串=总的串数-不美丽的串。而不美丽的串,首先满足条件,相邻的两个R之间的距离为奇数,易得。其次,所有的R之间的距离应该是相同的。反正法,假如R1,R2,R3,R1与R2之间的距离不等于R2与R3之间的距离,因为奇数+奇数=偶数,那么R1与R3之间距离是偶数,存在(R1+R3)/2点,但这个点不是R2,是G,所有事美丽串,与条件矛盾。简而言之就是R1与R3中间的判断点一个要是个R。 然后就好了,遍历R的起点,遍历所有奇数距离,判定是否所有的R都满足不美丽串条件,最后total-unbea。

    代码

    #include<iostream> #include<queue> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<string> #include<cctype> #include<algorithm> #include<vector> using namespace std; const long long mod=1e9+7; int main() { std::ios::sync_with_stdio(false); int t; cin>>t; while(t--) { string st; cin>>st; int unknow=0,r_num=0; for(int i=0;i<st.size();i++) { if(st[i]=='R')r_num++; if(st[i]=='?')unknow++; } int n=st.size(); long long unbea=0; if(r_num==0)unbea++; //R为0时,一种不美丽串特判 for(int i=0;i<n;i++) { if(st[i]=='R'||st[i]=='?') {int zz=0; if(st[i]=='R')zz=1; //判断初始的一个R是否满足 if(zz==r_num){unbea=(unbea+1)%mod;} for(int j=1;j+i<n;j+=2) { int z=zz; for(int k=i+j;k<n;k+=j) { if(st[k]=='R')z++; if(st[k]=='G')break; if(z==r_num){unbea=(unbea+1)%mod;} //满足一次就+1 } } } } long long cc=1; for(int i=0;i<unknow;i++){cc=(cc*2)%mod;} //这开始的时候写傻逼了 居然写成了cc*=2%mod; 这分明就没有Mod嘛。。。 long long ans=cc-unbea; cout<<ans<<endl; } return 0; }

    G

    题目链接

    http://acm.hdu.edu.cn/showproblem.php?pid=4371

    题意

    一个博弈问题,一个人x开始写0=s1,然后另外一个人y任选一个数加上去得到s2,然后x可以有两个选择,一个在n的基础上可以任意加一个数得到s3,s3不能大于n,或者任意减一个数得到s3,但减的时候s3>s1,即s3必须大于前前个数。当一个人无法操作时,即认输。

    题解

    一个贪心的博弈,首先我们排除选大的数的情况- -,因为你选大数,别人就选小的数求差,那么你就只能一直选大的数,直到最后输。这个游戏是由最小的数和上限来决定输赢的,上限/最小的数=奇数,则Alice赢,偶数则Bob赢。上面已经分析了,选大数一点赢的希望都没有,那就只有选最小的数,两个人都一直选最小的数,知道最后一个人没办法选了,决出胜负。

    代码

    #include<iostream> #include<queue> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<string> #include<cctype> #include<algorithm> #include<vector> using namespace std; int main() { int t; scanf("%d",&t); for(int i=1;i<=t;i++) { int n,m; scanf("%d%d",&n,&m); int minx=1e9+9; for(int j=0;j<m;j++) { int z; scanf("%d",&z); minx=min(minx,z); } int t=n/minx; if(t%2==1)printf("Case #%d: Bob\n",i); else printf("Case #%d: Alice\n",i); } return 0; }
    转载请注明原文地址: https://ju.6miu.com/read-1303346.html
    最新回复(0)