啊啊啊啊啊啊啊啊啊啊啊啊 ,再次感觉到了自己有多弱!!!!!
时间限制:20000ms
单点时限:1000ms
内存限制:256MB
描述
给定一个长度为 n 的序列 a[1..n],定义函数 f(b[1..m]) 的值为在 [0,m-1] 内满足如下条件的 i 的数目:
b 中前 i 个数异或起来的值小于 b 中前 i +1个数异或起来的值。
对于 a[1..n] 的每个子序列 b[1..m],求f(b[1..m])之和。
输入
第一行一个正整数 n。
接下来一共有 n 行。第 i+1 行包含一个非负整数 a[i]。
1 ≤ n ≤ 105
0 ≤ a[i] < 231
输出
输出答案对 998244353 取模后的值。
样例输入
2
1
2
样例输出
4
首先考虑a < a^b的情况, 显然需要a中二进制的0位在b中对应位是1且是b的最高位,不懂可以戳这里
然后就是需要对每个数 求贡献,
也就是找每个数 前面所构成在这个数最高位为0的异或和的个数,
可以设一个dp[31][0/1] 代表每一位位0/1的个数
转移就是
以上
int a[N],n;
LL dp[40][2],m[N];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
LL ans=0;
for(int i=0;i<=30;i++) dp[i][0]=1;
m[n]=1;
for(int i=n-1;i;i--) m[i]=m[i+1]*2%MOD;
for(int i=1,bt;i<=n;i++){
bt=0;
for(int j=30;j>=0;j--)if(a[i]&(1<break;}
ans=(ans+dp[bt][0]*m[i])%MOD;
for(int j=0;j<=30;j++){
int zero,one;
if(a[i]&(1<0]+dp[j][1] )%MOD;
one = (dp[j][0]+dp[j][1] )%MOD;
}
else {
zero = (dp[j][0]+dp[j][0] )%MOD;
one = (dp[j][1]+dp[j][1] )%MOD;
}
dp[j][0]=zero,dp[j][1]=one;
}
}
printf("%lld\n",ans%MOD);
return 0;
}
时间限制:20000ms
单点时限:1000ms
内存限制:256MB
描述
在写代码时,我们经常要用到类似 x × a 这样的语句( a 是常数)。众所周知,计算机进行乘法运算是非常慢的,所以我们需要用一些加法、减法和左移的组合来实现乘一个常数这个操作。具体来讲, 我们要把 x × a 替换成: (x<<a0)op1(x<<a1)op2(x<<a2)...opn(x<<an) 这样的形式,其中 opi 是+或者-。
举个例子:x × 15 = (x<<4) - (x<<0)。
在本题中,假设左移(包括左移0)和加法、减法所需要的时间都是一个单位的时间,上述的例子所需要的时间是3。
现在给定常数 a 的二进制形式,求实现 x × a 最少需要多少单位的时间。
输入
一个01串,表示 a 的二进制形式,从左到右分别是从高位到低位。
0 < 01串的长度之和 ≤ 10^6。
a > 0。
输出
输出一个数,表示最小需要多少单位的时间可以实现 x × a。
样例输入
1111
样例输出
3
————————————————————————————————————————
是个二分拆幂 http://www.cnblogs.com/atyuwen/archive/2012/08/04/pow2_partition.html
附本题代码
————————————————————————————————————————
#include
typedef long long int LL;
using namespace std;
const int N = 3e6+7;
/*************************************************/
char a[N];
int main(){a[0]='-';
scanf("%s",a+1);
int la = strlen(a+1);
int l=1,r=la;
while(l<=la&&a[l]=='0') l++;
while(r&&a[r]=='0') r--;
if(a[r]=='-') return 0*puts("0");
int u=1,d=1;
for(int i=r-1;i>=l;i--){
if(a[i]=='1') u=min(u,d)+1;
else d=min(u,d)+1;
}
printf("%d\n",u*2-1);
return 0;
}
时间限制:40000ms
单点时限:2000ms
内存限制:256MB
描述
有 n 个小朋友在投篮,他们的赛制是这样的:对于每轮,每个人投一颗球,没投进的就淘汰掉,无法参加下轮。特别地,如果所有人都没投进,那就没有人被淘汰。他们将一轮轮比下去直到最后只剩1个人。
现在已知每个小朋友投进的概率是 p,求期望几轮结束比赛。
输入
第一行三个整数 n, x, y。
题目中的 p = x / y。
1 ≤ n ≤ 105
1 ≤ x < y < 998244353
输出
输出答案对 998244353 取模后的值。
分数取模的方法:https://math.stackexchange.com/questions/586595/finding-modular-of-a-fraction
样例输入
2 1 2
样例输出
2
——————————————————————————————————
不会
——————————————————————————————————
时间限制:40000ms
单点时限:2000ms
内存限制:256MB
描述
给定一个长度为 n 的非负整数序列 a[1..n]。
你每次可以花费 1 的代价给某个 a[i] 加1或者减1。
求最少需要多少代价能将这个序列变成一个不上升序列。
输入
第一行一个正整数 n。
接下来 n 行每行一个非负整数,第 i 行表示 a[i]。
1 ≤ n ≤ 500000
0 < a[i] ≤ 10^9
输出
一个非负整数,表示答案。
样例解释
[5,3,4,5] -> [5,4,4,4]
样例输入
4
5
3
4
5
样例输出
2
——————————————————————————————————————————
首先这题有个结论, 最后得到的序列中的每一个元素都在原序列中
首先考虑 O(n2) 的dp
有了这个结论,我们可以直接dp
把 ai 变成第k大的那个序列所需要的最小花费就行了
但是这题数据范围明显需要 O(nlogn)
可以用左偏树降到 O(nlogn) ,然后就上了个左偏树的模板
附本题代码
——————————————————————————————————————————
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long int LL;
const LL maxn = 500000 + 10;
#define B printf("BUG\n");
LL a[maxn];
LL ans[maxn];
class Node {
public :
LL v;
LL h;
Node * ch[2];
Node(LL v) : v(v) { ch[0] = ch[1] = NULL; h = 0; }
};
class Seg {
public :
LL n;
Node * rt;
Seg(Node * rt, LL n) : rt(rt), n(n) {}
};
class Leftist {
public :
stack S;
Node * merge(Node * t1, Node * t2) {
if(t1 == NULL) return t2;
else if(t2 == NULL) return t1;
if(t1->v < t2->v) swap(t1, t2);
if(t1->ch[1] == NULL) {
t1->ch[1] = t2;
if(t1->ch[0] == NULL) { swap(t1->ch[0], t1->ch[1]); t1->h = 0; }
else {
if(t1->ch[0]->h < t1->ch[1]->h) swap(t1->ch[0], t1->ch[1]);
t1->h = t1->ch[1]->h + 1;
}
}
else {
t1->ch[1] = merge(t1->ch[1], t2);
if(t1->ch[0] == NULL) { swap(t1->ch[0], t1->ch[1]); t1->h = 0; }
else {
if(t1->ch[0]->h < t1->ch[1]->h) swap(t1->ch[0], t1->ch[1]);
t1->h = t1->ch[1]->h + 1;
}
}
return t1;
}
void solve(LL x) {
LL num = 1;
Node * t1 = new Node(x);
while(!S.empty()) {
Seg * s2 = S.top();
if(t1->v < s2->rt->v) {
LL flag = false;
if(num % 2 && s2->n % 2) flag = true;
t1 = merge(t1, s2->rt);
num += s2->n;
if(flag) {
Node * tmp = t1;
t1 = merge(t1->ch[0], t1->ch[1]);
delete tmp;
}
S.pop();
delete s2;
}
else break;
}
Seg * s2 = new Seg(t1, num);
S.push(s2);
}
void removetree(Node * rt) {
if(rt->ch[0] == NULL && rt->ch[1] == NULL) {
delete rt;
rt = NULL;
return ;
}
if(rt->ch[0]) removetree(rt->ch[0]);
if(rt->ch[1]) removetree(rt->ch[1]);
delete rt;
rt = NULL;
}
void remove() {
while(!S.empty()) {
removetree(S.top()->rt);
delete S.top();
S.pop();
}
}
};
int main() {
LL n;
while(scanf("%lld", &n) != EOF) {
Leftist lt;
for( LL i=0; iscanf("%lld", &a[i]);
lt.solve(a[i]);
}
LL k = 0;
while(!lt.S.empty()) {
Seg * f = lt.S.top(); lt.S.pop();
for( LL i=0; in; i++ ) {
ans[k++] = f->rt->v;
}
}
LL res = 0;
for( LL i=k-1; i>=0; i-- ) res += abs(ans[i] - a[n-i-1]);
lt.remove();
Leftist lt2;
for( LL i=0; i2; i++ ) swap(a[i], a[n-i-1]);
for( LL i=0; i0;
while(!lt2.S.empty()) {
Seg * f = lt2.S.top(); lt2.S.pop();
for( LL i=0; in; i++ ) {
ans[k++] = f->rt->v;
}
}
LL res2 = 0;
for( LL i=k-1; i>=0; i-- ) res2 += abs(ans[i] - a[n-i-1]);
lt2.remove();
printf("%lld\n",res2);
}
return 0;
}