Codeforces Round 251 (Div. 2)
layout: post
title: Codeforces Round 251 (Div. 2)
author: "luowentaoaa"
catalog: true
tags:
mathjax: true
- codeforces
- 模拟
A.[Devu, the Singer and Churu, the Joker (签到)
题意
主角有N首不同时长的歌曲,每首歌曲之间需要相隔10分钟,并且歌曲必须连续,再主角唱完歌的时候可以表演每次五分钟的其他节目。问最多表演多少场其他节目, 不能完成演唱输出-1
思路
直接先按照题意安排歌曲,然后再在空缺的时间中填充魔术。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int a[maxn];
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int n,d;
cin>>n>>d;
for(int i=1;i<=n;i++)cin>>a[i];
if((n-1)*10>=d){
cout<<-1<<endl;return 0;
}
int cnt=0;
int ex=d-(n-1)*10;
int num=0;
for(int i=1;i<=n;i++){
if(i!=1)num+=10,cnt+=2;
num+=a[i];
}
if(num>d){
cout<<-1<<endl;return 0;
}
else{
cnt+=(d-num)/5;
cout<<cnt<<endl;
}
return 0;
}
B.Devu, the Dumb Guy (贪心)
题意
n个课程,每个课程都有ci个章节,完成一章需要X分钟,但是如果完成一个课程后面的课程每章都会减少一分钟(最少不低于1分钟),问少需要几分完成所有课程。
题解
直接排序 然后根据题意模拟贪心。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int a[maxn];
int cnt[maxn];
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int n,x;
cin>>n>>x;
for(int i=1;i<=n;i++)cin>>a[i];
sort(a+1,a+1+n);
ll sum=0;
for(int i=1;i<=n;i++){
sum+=a[i]*max(1LL*(x-i+1LL),1LL);
}
cout<<sum<<endl;
return 0;
}
C.Devu and Partitioning of the Array (大模拟)
题意
给出N个数,让你分成k块,其中p块的和为偶数
思路
只要知道偶数+偶数=偶数,奇数+奇数=偶数 奇数+偶数=奇数的特性就可以做了,
不过情况比较多需要讨论
先把奇数偶数分类,然后如果奇数比较多,就判断奇数多出来的那些可不可以组成偶数(也就是多出来的是不是偶数个)
注意讨论奇数和偶数分别为0的情况。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
ll a[maxn];
stack<int>odd,even,exeven,exodd;
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int n,k,p;
cin>>n>>k>>p;
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]&1)odd.push(a[i]);
else even.push(a[i]);
}
int oddnum=odd.size();
int odd_need_num=k-p;
int even_need_num=p;
if(odd_need_num>oddnum){
cout<<"NO"<<endl;return 0;
}
else{
if((oddnum-odd_need_num)%2!=0){
cout<<"NO"<<endl;return 0;
}
else{
int ex=oddnum-odd_need_num;
for(int i=1;p!=0&&i<=ex;i++){
exeven.push(odd.top());
odd.pop();
}
if(!p){
while(!even.empty()){
exodd.push(even.top());
even.pop();
}
}
if(ex/2+even.size()<even_need_num){
cout<<"NO"<<endl;return 0;
}
cout<<"YES"<<endl;
for(int i=1;i<odd_need_num;i++){
cout<<1<<" "<<odd.top()<<endl;
odd.pop();
}
if(!odd.empty()){
cout<<odd.size()+exodd.size()<<" ";
while(!odd.empty()){
cout<<odd.top()<<" ";
odd.pop();
}
while(!exodd.empty()){
cout<<exodd.top()<<" ";
exodd.pop();
}
cout<<endl;
}
for(int i=1;i<p;i++){
if(!even.empty()){
cout<<1<<" "<<even.top()<<endl;
even.pop();
}
else{
cout<<2<<" "<<exeven.top();
exeven.pop();
cout<<" "<<exeven.top()<<endl;
exeven.pop();
}
}
if(even.size()+exeven.size()==0)return 0;
cout<<even.size()+exeven.size()<<" ";
while(!even.empty()||!exeven.empty()){
if(!even.empty()){
cout<<even.top()<<" ";
even.pop();
}
else{
cout<<exeven.top()<<" ";
exeven.pop();
cout<<exeven.top()<<" ";
exeven.pop();
}
}
}
}
return 0;
}
D.Devu and his Brother (三分)
题意
两个数组A,B.想要数组A的最小值不比数组B的最大值小,一次操作可以让某个数字的一个元素增大或者减小1 问达成目的最少需要几次操作。
思路
题目的意思就是找出一个值X使得A中的所有元素都大于等于X,B中的元素小于等于X。
所以答案就是
\]
假设这个x是最优的解,那么X增大或者减小都会使得ans变大,所以题目就是一个凹函数求最小值了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
ll a[maxn];
ll b[maxn];
int n,m;
ll check(ll x){
ll ans=0;
for(int i=1;i<=n;i++)if(a[i]<x)ans+=x-a[i];
for(int i=1;i<=m;i++)if(b[i]>x)ans+=b[i]-x;
return ans;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
cin>>n>>m;
for(int i = 1; i <= n; i++){
cin>>a[i];
}
for(int i = 1; i <= m; i++){
cin>>b[i];
}
ll l=0,r=1e11,ans=inf;
for(int i=1;i<=100;i++){
ll m1=(l+r)/2;
ll m2=(m1+r)/2;
ll ans1=check(m1),ans2=check(m2);
if(ans1>ans2){
l=m1;
ans=min(ans,ans2);
}
else{
r=m2;
ans=min(ans,ans1);
}
}
cout<<ans<<endl;
return 0;
}
E.Devu and Birthday Celebration (莫比乌斯反演,素因子分解,计数原理,组合数学)
题意
Q次询问 给出一个数N 让你分成F份,使得这F份的和为N并且这F份数 最大公约数为1,问有多少种分法。Q,N,F范围都是1-1e5。
思路
如果不考虑公约数 那么答案就是Cn-1,f-1。
设F(n,k)为n个数分成F份并且最大公约数为1的答案数
所以
\]
然后直接递归写就行。
\]
\]
可知
\]
同时
\]
于是根据莫比乌斯反演因数反演
\]
/*
莫比乌斯反演
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
ll inv[maxn],p[maxn];
ll ksm(ll x,ll n){
ll ans=1;
while(n){
if(n&1)ans=(ans*x)%mod;
x=(x*x)%mod;
n>>=1;
}
return ans;
}
int prime[maxn];
bool notprime[maxn];
int mu[maxn];
void init(int n){
mu[1]=1;
int tot=0;
for(int i=2;i<=n;i++){
if(!notprime[i])prime[++tot]=i,mu[i]=-1;
for(int j=1;j<=tot;j++){
if(i*prime[j]>n)break;
notprime[i*prime[j]]=true;
if(i%prime[j]==0){
mu[i*prime[j]]=0;
break;
}
else mu[i*prime[j]]=-mu[i];
}
}
inv[0]=p[0]=1;
for(int i=1;i<=n;i++)
p[i]=p[i-1]*i%mod,inv[i]=ksm(p[i],mod-2);
}
ll cal(int n,int m){
if(n<m)return 0LL;
return p[n]*inv[n-m]%mod*inv[m]%mod;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
init(1e5);
int q;
cin>>q;
while(q--){
ll n,f;
cin>>n>>f;
ll ans=0;
for(int i=1;i*i<=n;i++){
if(n%i==0){
ans=(ans+mu[i]*cal(n/i-1,f-1)+mod)%mod;
if(n/i!=i)ans=(ans+mu[n/i]*cal(i-1,f-1)+mod)%mod;
}
}
cout<<ans<<endl;
}
return 0;
}
/*
枚举GCD值
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
ll inv[maxn],p[maxn];
ll ksm(ll x,ll n){
ll ans=1;
while(n){
if(n&1)ans=(ans*x)%mod;
x=(x*x)%mod;
n>>=1;
}
return ans;
}
vector<int>G[maxn];
void init(int n){
inv[0]=p[0]=1;
for(int i=1;i<=n;i++)
p[i]=p[i-1]*i%mod,inv[i]=ksm(p[i],mod-2);
for(int i=2;i<=n;i++){
for(int j=i;j<=n;j+=i){
G[j].push_back(i);
}
}
}
ll cal(int n,int m){
if(n<m)return 0LL;
return p[n]*inv[n-m]%mod*inv[m]%mod;
}
ll vis[maxn];
int who[maxn];
ll F(int n,int k,int q){
if(who[n]==q)return vis[n];
ll ans=cal(n-1,k-1);
for(int i=0;i<G[n].size();i++){
ans=(ans-F(n/G[n][i],k,q)+mod)%mod;
}
who[n]=q;
vis[n]=ans;
return ans;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
init(1e5);
int q;
cin>>q;
while(q){
ll n,f;
cin>>n>>f;
cout<<F(n,f,q)<<endl;
q--;
}
return 0;
}
/*
枚举GCD倍数
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
ll inv[maxn],p[maxn];
ll ksm(ll x,ll n){
ll ans=1;
while(n){
if(n&1)ans=(ans*x)%mod;
x=(x*x)%mod;
n>>=1;
}
return ans;
}
void init(int n){
inv[0]=p[0]=1;
for(int i=1;i<=n;i++)
p[i]=p[i-1]*i%mod,inv[i]=ksm(p[i],mod-2);
}
ll cal(int n,int m){
if(n<m)return 0LL;
return p[n]*inv[n-m]%mod*inv[m]%mod;
}
vector<int> get(int n){
vector<int>G;
for(int i=2;i*i<=n;i++){
if(n%i==0){
G.push_back(i);
while(n%i==0)n/=i;
}
}
if(n!=1)G.push_back(n);
return G;
}
ll F(int n,int k){
vector<int>G=get(n);
ll ans=0,num=1<<G.size();
for(int i=0;i<num;i++){
ll tmp=1,sign=1;
for(int j=0;j<G.size();j++){
if(i&(1<<j)){
sign*=-1;
tmp*=G[j];
}
}
ans=(ans+sign*cal(n/tmp-1,k-1)%mod+mod)%mod;
}
return ans;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
init(1e5);
int q;
cin>>q;
while(q--){
ll n,f;
cin>>n>>f;
cout<<F(n,f)<<endl;
}
return 0;
}
Codeforces Round 251 (Div. 2)的更多相关文章
- Codeforces Round#251(Div 2)D Devu and his Brother
--你以为你以为的.就是你以为的? --有时候还真是 题目链接:http://codeforces.com/contest/439/problem/D 题意大概就是要求第一个数组的最小值要不小于第二个 ...
- Codeforces Round #251 (Div. 2) C. Devu and Partitioning of the Array
注意p的边界情况,p为0,或者 p为k 奇数+偶数 = 奇数 奇数+奇数 = 偶数 #include <iostream> #include <vector> #include ...
- Codeforces Round #251 (Div. 2) B. Devu, the Dumb Guy
注意数据范围即可 #include <iostream> #include <vector> #include <algorithm> using namespac ...
- Codeforces Round #251 (Div. 2) A - Devu, the Singer and Churu, the Joker
水题 #include <iostream> #include <vector> #include <algorithm> using namespace std; ...
- Codeforces Round #366 (Div. 2) ABC
Codeforces Round #366 (Div. 2) A I hate that I love that I hate it水题 #I hate that I love that I hate ...
- Codeforces Round #354 (Div. 2) ABCD
Codeforces Round #354 (Div. 2) Problems # Name A Nicholas and Permutation standard input/out ...
- Codeforces Round #368 (Div. 2)
直达–>Codeforces Round #368 (Div. 2) A Brain’s Photos 给你一个NxM的矩阵,一个字母代表一种颜色,如果有”C”,”M”,”Y”三种中任意一种就输 ...
- cf之路,1,Codeforces Round #345 (Div. 2)
cf之路,1,Codeforces Round #345 (Div. 2) ps:昨天第一次参加cf比赛,比赛之前为了熟悉下cf比赛题目的难度.所以做了round#345连试试水的深浅..... ...
- Codeforces Round #279 (Div. 2) ABCDE
Codeforces Round #279 (Div. 2) 做得我都变绿了! Problems # Name A Team Olympiad standard input/outpu ...
随机推荐
- Mac Java配置JAVA——HOME
命令行中输入: export JAVA_HOME=$(/usr/libexec/java_home)
- 【题解】[国家集训队]Crash的数字表格 / JZPTAB
求解\(\sum_{i = 1}^{n}\sum_{j = 1}^{m}lcm\left ( i,j \right )\). 有\(lcm\left ( i,j \right )=\frac{ij}{ ...
- 【题解】SCOI2010幸运数字
最近在学习容斥相关,于是就看到了这个题.一开始以为是补集转化,但是观察一下马上发现不可行,好像直接做会比较容易一些.一个数满足要求的充要条件即为是一个幸运数字的倍数,那么容斥可以轻松搞定,只要枚举是一 ...
- python实现关联规则
代码中Ci表示候选频繁i项集,Li表示符合条件的频繁i项集 # coding=utf-8 def createC1(dataSet): # 构建所有1项候选项集的集合 C1 = [] for tran ...
- BZOJ 1040: [ZJOI2008]骑士 | 在基环外向树上DP
题目: http://www.lydsy.com/JudgeOnline/problem.php?id=1040 题解: 我AC了 是自己写的 超开心 的 考虑断一条边 这样如果根节点不选答案一定正确 ...
- Linux(CentOS)用split命令分割文件
在 Linux 里,稍加不注意有可能会产生很大体积的日志文件,哪怕几百M,拖下来分析也很浪费时间,这个时候,如果可以把文件切割成 N 个小文件,拿最后一个文件就可以看到最近的日志了.有一些手段,比如用 ...
- Dilworth定理证明
命题:偏序集能划分成的最少的全序集的个数与最大反链的元素个数相等. (离散数学结构第六版课本P245:把一个偏序集划分成具有全序的子集所需要的最少子集个数与元素在偏序下都是不可比的最大集合的基数之间有 ...
- Robot POJ - 1376
The Robot Moving Institute is using a robot in their local store to transport different items. Of co ...
- Android百度定位地图使用--文章集锦
Android百度定位API使用方法 Android百度地图开发(一)之初体验 AndroidNote013.在百度地图上画出轨迹 Android学习笔记之百度地图(分条目覆盖物:ItemizedOv ...
- 搭建eova开发环境
1.安装好maven 2.下载Eova项目解压到文件夹eova下 3.dos命令到eova文件夹下执行mvn eclipse:eclipse(注:构建eclipse项目命令) 4.修改*.tag文件错 ...