http://codeforces.com/contest/810
这场题目确实不错,E也是挺难的,我看了看数位dp还是算了.
你有n个数字,每个数字在1-k之间.
问你最少添加多少个1-k间的数字,使得这些数字的平均数小数部分四舍五入之后等于k.
明显必须添加 k k ,我们可以暴力添加i i 个 k k ,看看添加多少个的时候四舍五入等于k k .
#include //Ithea Myse Valgulious
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rec register char
#define rel register ll
#define gc getchar
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
inline int read(){
int x=0,f=1;char c=gc();
for (;!isdigit(c);c=gc()) f^=c=='-';
for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
return f?x:-x;
}
template <typename mitsuha>
inline bool read(mitsuha &x){
x=0;int f=1;char c=gc();
for (;!isdigit(c)&&~c;c=gc()) f^=c=='-';
if (!~c) return 0;
for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
return x=f?x:-x,1;
}
template <typename mitsuha>
inline int write(mitsuha x){
if (!x) return 0&pc(48);
if (x<0) x=-x,pc('-');
int bit[20],i,p=0;
for (;x;x/=10) bit[++p]=x%10;
for (i=p;i;--i) pc(bit[i]+48);
return 0;
}
inline char fuhao(){
char c=gc();
for (;isspace(c);c=gc());
return c;
}
}using namespace chtholly;
using namespace std;
int n=read(),k=read();
int main(){
int i,ans=0;
for (i=1;i<=n;++i) ans+=read();
for (i=0;;i++){
if (floor(1.*(ans+k*i)/(n+i)+0.5)>=k) break;
}write(i);
}
给你n个pair,每个pair包含两个数k,l,你可以选择f个pair,使得这个pair的k乘以二.
求最后所有pair的min(k,l)之和的最大值.
贪心,把这些pair按照一定规则排序,然后模拟求一下.
很明显,排序的依据是当 k×2 k × 2 之后能让 min(k,l) m i n ( k , l ) 增加的数量.
当 k×2<l k × 2 < l 的时候 增加 k k ,k<l k < l 且 k×2≥l k × 2 ≥ l 的时候增加 l−k l − k .
按照这个排序即可.
一开始按照错误的方法排序wa了好几发.
#include //Ithea Myse Valgulious
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rec register char
#define rel register ll
#define gc getchar
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
inline int read(){
int x=0,f=1;char c=gc();
for (;!isdigit(c);c=gc()) f^=c=='-';
for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
return f?x:-x;
}
template <typename mitsuha>
inline bool read(mitsuha &x){
x=0;int f=1;char c=gc();
for (;!isdigit(c)&&~c;c=gc()) f^=c=='-';
if (!~c) return 0;
for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
return x=f?x:-x,1;
}
template <typename mitsuha>
inline int write(mitsuha x){
if (!x) return 0&pc(48);
if (x<0) x=-x,pc('-');
int bit[20],i,p=0;
for (;x;x/=10) bit[++p]=x%10;
for (i=p;i;--i) pc(bit[i]+48);
return 0;
}
inline char fuhao(){
char c=gc();
for (;isspace(c);c=gc());
return c;
}
}using namespace chtholly;
using namespace std;
const int yuzu=1e5;
struct node{
ll k,l,d;
void rd(){
k=read(),l=read();
d=k*2l?0:l-k;
}
bool operator <(const node &b) const{
return d>b.d;
}
}a[yuzu|10];
int main(){
int i,n=read(),f=read();
for (i=1;i<=n;++i) a[i].rd();
sort(a+1,a+n+1);
ll ans=0;
for (i=1;i<=f;++i) ans+=min(a[i].k*2,a[i].l);
for (i=f+1;i<=n;++i) ans+=min(a[i].k,a[i].l);
write(ans);
}
定义F(a)是集合a中最大的元素减去最小元素的差.给出一个集合,求该集合的所有子集的F函数值之和mod 10^9+7.
从小到大排序,枚举每一个元素作为子集的最小元素.
我们来看一下,当最小元素是 a[1] a [ 1 ] 的时候,看看最大元素,比如说最大元素是 a[i] a [ i ] ,则必然有 2i−2 2 i − 2 个集合符合这样的条件.( a[2−i] a [ 2 − i ] 都可以任意取或者不取.)
此时需要减掉 a[1] a [ 1 ] 的个数就是 20+21+22+...+2n−2 2 0 + 2 1 + 2 2 + . . . + 2 n − 2 .
减掉 a[2] a [ 2 ] 的个数是 20+21+22+23+...2n−3 2 0 + 2 1 + 2 2 + 2 3 + . . .2 n − 3 .
我们可以算出减去每一个数的个数.
接下来将每个最大元素对应的集合个数覆盖上去,列表如下:
最小元素 最大元素 a[1] a[2] a[3] a[4] a[5] ... a[n]
a[1] 0 1 2 4 8 2^(n-2)
a[2] 0 1 2 4 2^(n-3)
a[3] 0 1 2 2^(n-4)
发现了吧.
加上 a[n] a [ n ] 的个数很明显和减去 a[1] a [ 1 ] 的个数相等.
因此这样对每个数求两个等比数列之和即可.
如果预处理 2 2 的幂次,时间复杂度还能够更低.
#include //Ithea Myse Valgulious
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rec register char
#define rel register ll
#define gc getchar
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
inline int read(){
int x=0,f=1;char c=gc();
for (;!isdigit(c);c=gc()) f^=c=='-';
for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
return f?x:-x;
}
template <typename mitsuha>
inline bool read(mitsuha &x){
x=0;int f=1;char c=gc();
for (;!isdigit(c)&&~c;c=gc()) f^=c=='-';
if (!~c) return 0;
for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
return x=f?x:-x,1;
}
template <typename mitsuha>
inline int write(mitsuha x){
if (!x) return 0&pc(48);
if (x<0) x=-x,pc('-');
int bit[20],i,p=0;
for (;x;x/=10) bit[++p]=x%10;
for (i=p;i;--i) pc(bit[i]+48);
return 0;
}
inline char fuhao(){
char c=gc();
for (;isspace(c);c=gc());
return c;
}
}using namespace chtholly;
using namespace std;
const int yuzu=3e5,mod=1e9+7;
typedef ll fuko[yuzu|10];
fuko a;
ll kasumi(ll a,ll b=mod-2){
ll s=1;
for (;b;b>>=1,a=a*a%mod) if (b&1) s=s*a%mod;
return s;
}
ll he(int q,int l,int r){
if (l>r) return 0;
return (kasumi(q,r+1)-kasumi(q,l)+mod)%mod;
}
int main(){
int i,n=read();
for (i=1;i<=n;++i) a[i]=read();
sort(a+1,a+n+1);
ll llx=0;
for (i=1;i<=n;++i){
llx=(llx+a[i]*he(2,0,i-2)-a[i]*he(2,0,n-i-1)+mod)%mod;
}write(llx);
}
交互题.
从1-n n个数里,电脑选择其中k个数组成的一个集合.你需要猜出这k个数中的两个.
你每次可以询问x,y两个数,定义a是k个数中最接近x的数,b是k个数中最接近y的数.
如果|x-a|<=|y-b|,回复是"TAK",否则是"NIE".你最多询问60次.
询问的格式是"1 x y",给出的答案是"2 x y",给出答案后立即结束程序.
我们每次询问连续的两个数,如果答案是TAK
,左边肯定有一个数,否则右边肯定有一个数.
这样二分可以找出一个数.
然后在x x 的左边或者右边找到另一个数 y y 即可.
#include //Ithea Myse Valgulious
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rec register char
#define rel register ll
#define gc getchar
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
inline int read(){
int x=0,f=1;char c=gc();
for (;!isdigit(c);c=gc()) f^=c=='-';
for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
return f?x:-x;
}
template <typename mitsuha>
inline bool read(mitsuha &x){
x=0;int f=1;char c=gc();
for (;!isdigit(c)&&~c;c=gc()) f^=c=='-';
if (!~c) return 0;
for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
return x=f?x:-x,1;
}
template <typename mitsuha>
inline int write(mitsuha x){
if (!x) return 0&pc(48);
if (x<0) x=-x,pc('-');
int bit[20],i,p=0;
for (;x;x/=10) bit[++p]=x%10;
for (i=p;i;--i) pc(bit[i]+48);
return 0;
}
inline char fuhao(){
char c=gc();
for (;isspace(c);c=gc());
return c;
}
}using namespace chtholly;
using namespace std;
int n,k,a,b;
bool query(int x,int y){
if (x<0||y>n) return 0;
printf("1 %d %d\n",x,y);
fflush(stdout);
string ans;cin>>ans;
return ans=="TAK";
}
int get(int l,int r){
if (l>r) return -1;
for (;lint mid=l+r>>1;
query(mid,mid+1)?r=mid:l=mid+1;
}
return l;
}
int main(){
n=read(),k=read();
a=get(1,n),b=get(1,a-1);
if (!query(b,a)) b=get(a+1,n);
printf("2 %d %d\n",a,b);
}
谢谢大家.