题目链接
有 n n n个硬币有着 2 1 , 2 2 , ⋯ , 2 n 2^1,2^2,\cdots,2^n 21,22,⋯,2n的重量,是偶数。
把硬币分成数量相同的两堆,使得两堆的重量相差最小
根据等比数列的求和公式 s n = 2 ( 1 − 2 n ) 1 − 2 = 2 n + 1 − 1 s_n=\frac{2(1-2^n)}{1-2}=2^{n+1}-1 sn=1−22(1−2n)=2n+1−1。
所以我们的得出一个质量为 2 n 2^n 2n的硬币的那堆比它小的所有硬币相加的质量还要大 1 1 1。
为了使两堆的相差最小,根据贪心,我们很容易得到可以分成这样的两堆其中一堆是 2 1 , 2 2 , 2 n / 2 − 1 , 2 n 2^1,2^2,2^{n/2-1},2^n 21,22,2n/2−1,2n。
#include
#define DEBUG puts("Here is a BUG")
#define PI 3.1415926535897932626
#define all(a) a.begin(),a.end()
typedef long long ll;
using namespace std;
const double eps=1e-8;
const int MAXN=(int)1e5+5;
const int MOD=(int)1e9+7;
const int INF=0x3f3f3f3f;
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
while (T--)
{
ll a,b;
a=b=0;
int n;
cin>>n;
for(int i=1;i<n/2;i++)a+=(1ll<<i);
a+=(1ll<<n);
for(int i=n/2;i<n;i++)b+=(1ll<<i);
cout<<a-b<<endl;
}
return 0;
}
题目链接
有一个长度为 n n n的排列,我们希望添加一些数字使得它所有大小为 k k k的子序列的和相同。
我们先考虑无法构造的情况,就是该序列中的数值的种类个数大于k。
然后我们考虑构造一个循环串,所以我先尝试了一下将数字按照出现的顺序依次排列作为循环串的循环节,如果循环节的长度小于 k k k那么在循环节的末尾补数值 k k k,使得长度为 k k k,然后循环的次数为 n n n。结果一发 WA估计是构造的太长了。
接下来考虑优化,我们发现不一定循环节的长度需要构造到k,长度只需要是 k k k的因数就好了。
#include
#define DEBUG puts("Here is a BUG")
#define PI 3.1415926535897932626
#define all(a) a.begin(),a.end()
typedef long long ll;
using namespace std;
const double eps=1e-8;
const int MAXN=(int)1e5+5;
const int MOD=(int)1e9+7;
const int INF=0x3f3f3f3f;
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
int a[MAXN];
map<int,int>mp;
set<int> s;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T,n,k;
cin>>T;
while (T--)
{
cin>>n>>k;
s.clear(),mp.clear();
int tmp,cur=0;
memset(a,0,sizeof(a));
for (int i = 0; i < n; i++)
{
cin>>tmp;
if(!s.count(tmp))s.insert(tmp),mp[cur]=tmp,cur++;
}
if(cur>k){cout<<-1<<endl;continue;}
while(k%cur>0)mp[cur++]=k;
cout<<n*cur<<endl;
for (int i = 0; i < n; i++)for (int j = 0; j < cur; j++)cout<<mp[j]<<" ";
cout<<endl;
}
return 0;
}
题目链接
将字符串 s s s拆分成 k k k个字符串,这些字符串不一定要是 s s s的子串,求出在所有分出的字符串中的最大字典序的字符串的字典序最小。
这题可以分成三种情况
#include
#define DEBUG puts("Here is a BUG")
#define PI 3.1415926535897932626
#define all(a) a.begin(),a.end()
typedef long long ll;
using namespace std;
const double eps=1e-8;
const int MAXN=(int)1e5+5;
const int MOD=(int)1e9+7;
const int INF=0x3f3f3f3f;
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
char buf[MAXN];
int n,k,T;
int a[26];
cin>>T;
while (T--)
{
cin>>n>>k;
cin>>buf;
memset(a,0,sizeof(a));
for (int i = 0; i < n; i++)a[buf[i]-'a']++;
sort(buf,buf+n);
//第一种
if (a[buf[0]-'a']<k)
{
int cur=a[buf[0]-'a'];
cout<<buf[k-1]<<endl;
continue;
}
//第二种
int m=0;
for (int i=0;i<26;i++)if(a[i])m++;
if(m==1)
{
cout<<string((n+k-1)/k,buf[0])<<endl;
continue;
}
if(m==2&&a[buf[0]-'a']==k)
{
cout<<buf[0];
for (int i = 0; i < n; i++)if(buf[0]!=buf[i]){cout<<string((a[buf[i]-'a']+k-1)/k,buf[i])<<endl;break;}
continue;
}
//第三种
cout<<buf+k-1<<endl;
}
return 0;
}
题目链接
初始的时候你有1个质量为1的细菌。
每天细菌都可以分裂成两块,然后每天晚上每个细菌的重量都会+1。
给定一个细菌质量,求所需要的最小天数和每天分裂的情况
设 a i a_i ai为第 i i i天的最大质量, b i b_i bi为第 i i i的细菌最多的数量。
我们可以得出如下的递推式
a i = a i − 1 + 2 b i − 1 b i = 2 b i − 1 a_i=a_{i-1}+2b_{i-1}\\ b_i=2b_{i-1} ai=ai−1+2bi−1bi=2bi−1
然后我们可以根据二分查找找到所需要的最少天数 k k k
然后接下来考虑分裂方案,我们分为两种情况来考虑
#include
#define DEBUG puts("Here is a BUG")
#define PI 3.1415926535897932626
#define all(a) a.begin(),a.end()
typedef long long ll;
using namespace std;
const double eps=1e-8;
const int MAXN=(int)1e5+5;
const int MOD=(int)1e9+7;
const int INF=0x3f3f3f3f;
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
ll a[2000],an[2000];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int cur=0;
a[0]=1,an[0]=1;
while (a[cur]<(ll)1e9)
{
cur++;
a[cur]=a[cur-1]+an[cur-1]*2;
an[cur]=an[cur-1]*2;
}
int T,n;
cin>>T;
while (T--)
{
cin>>n;
int ans=lower_bound(a+1,a+cur,n)-a;
cout<<ans<<endl;
int x,y;
if(ans==1)
{
if(n==2)cout<<0<<endl;else cout<<1<<endl;
continue;
}
if(a[ans-1]+an[ans-1]>=n)
{
ll k=n-a[ans-2];
if(k&1)y=1;
else y=0;
x=k/2-an[ans-2];
for (int i = 1; i <= ans-2; i++)cout<<an[i-1]<<" ";
cout<<x<<" "<<y<<endl;
}else
{
for (int i = 1; i <= ans-1; i++)cout<<an[i-1]<<" ";
cout<<(n-a[ans-1]-an[ans-1])<<endl;
}
}
return 0;
}