版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hqh131360239/article/details/82963992
思路:再来读一遍题目,就是一个取石子游戏,首先肯定第一反应就是暴力啊,暴力k值,然后直到找到满足条件的最小的k值结束,但是肯定会超时。我开始有闪过这样一个想法,都是错误的哈(只要取大于等于一半即可,妞妞取得一半是最少的,牛牛取得一半消耗的次数,然后去除,直接得到m,哈哈牛牛的每次取值是总数的1/10,不断变化的)。其实很简单k值得取值范围1~1^18,二分找到满足条件的k值啊,long long的范围为2^64,也就是对于最大的数据,64次尝试也能过。想多了,傻逼了,暴力+二分即可过。
误区:
①不低于一半,大于等于一半(n+1)/2
②1/10向下取整(直接整除即可)
③注意暴力的时候,最后一次妞妞取的时候,会出现不够取得时候。
方法一直接暴力超时;方法二暴力+二分,应该能过。
/*#include<iostream>
using namespace std;
int main(){
long long n;
while(cin>>n){
long long x=(n+1)/2;
for(long long i=1;i<=x;i++){
long long xx=n;
long long sum=0;
while(xx>0){
xx-=i;
sum+=i;
xx-=xx/10;
if(sum>=x) break;
}
if(sum>=x) {cout<<i<<endl;break;}
}
}
}*/
#include<iostream>
using namespace std;
int main(){
long long n;
while(cin>>n){
long long x=(n+1)/2;
for(long long i=1;i<=x;i++){
long long xx=n;
long long sum=0;
while(xx>0){
xx-=i;
if(xx<0) { //不够取
sum+=(i+xx);
break;
}else sum+=i;
xx-=xx/10;
if(sum>=x) break;
}
if(sum>=x) {cout<<i<<endl;break;}
}
}
}
#include<iostream>
#include<math.h>
#include<stdio.h>
using namespace std;
int main(){
long long n;
//freopen("1.txt","w",stdout);
while(cin>>n){
//n=1000000000000000000;
long long x=(n+1)/2;
long long l=1;
long long r=x;
long long ans=1000000000000000000;
while(l<=r){
long long i=(l+r)/2;
long long xx=n;
long long sum=0;
while(xx>0){
xx-=i;
if(xx>=0){
sum+=i;
xx-=xx/10;
}else{//一次拿m个,不够拿的情况
sum+=(i+xx);
}
}
if(sum>=x) {
//找到满足条件的了,记录最小值
if(i<=ans){
ans=i;
}
r=i-1;
}else{
l=i+1;
}
}
cout<<ans<<endl;
}
return 0;
}
思路:就是统计字母的个数,然后找取个数和为m,且个数的平方最大。策略就是先选取个数最大的,依次选择即可。
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int n,m;
string str;
while(cin>>n>>m){
cin>>str;
int len=str.length();
int a[26]={0};
//统计每个字母的个数
for(int i=0;i<len;i++){
a[str[i]-65]++;
}
sort(a,a+26);
//计算分数
int sum=0;
for(int i=25;i>=0;i--){
if(a[i]>=m){
sum+=m*m;
break;
}else{
sum+=a[i]*a[i];
m-=a[i];
}
}
cout<<sum<<endl;
}
return 0;
}
思路:①把第一个数和第二个数的素数公约数全部找出来,合并,共n组数据;然后统计n组数据出现的个数,利用Map,最后遍历哪个素数的键值为n且最大,然后输出即可。
②其实两个公约数的∪集,即两个数的最小公倍数;求n个数的最大公约数。最大素数公约数一定是最大公约数的约数。如:a和b的最大公约数c,a/c和b/c之后必定没有公约数了,那么a和b的最大素数公约数必定是c的公约数。注意:最大公约数是3、5、7、11不需要操作,如果最大公约数不是素数,那么需要处理(比如:21->7)
#include <iostream>
using namespace std;
long long gcd(long long a,long long b){
return a%b==0?b:gcd(b,a%b);
}
int main()
{
int n;
cin>>n;
long long a[150005];
long long x,y;
for(int i=0;i<n;i++){
cin>>x>>y;
a[i]=x/gcd(x,y)*y; //先除后乘,防止溢出
}
long long temp=a[0];
if(temp==1){
cout<<"-1"<<endl;
return 0;
}else
for(int i=1;i<n;i++){
temp=gcd(a[i],temp);
if(temp==1){
cout<<"-1"<<endl;
return 0;
}
}
//求temp的最大素数公约数
int i;
for(i=2;;i++){
while(temp%i==0){ //神奇的操作
temp/=i;
}
if(temp==1) break;
}
cout<<i<<endl;
return 0;
}
//其实就是求最大公约数,不要被出题人迷惑了
//最大公约数,一定包含最大素数公约数
//a和b的最大公约数c,a/c和b/c之后必定没有公约数了
//那么a和b的最大素数公约数必定是c的公约数