T1
正解贪心。
在使用钞票最少前提下保证浪费的钱数最少
保证第一条,在还没达到规定钱数时尽可能使用大面值钞票
保证第二条,在现有钞票不满足要求前提下,尽量选面值小的放
综上,代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
using namespace std;
const int MAXN = 100000 + 50;
struct zt
{
LL v,b;
}B[MAXN << 1];
int x,y,cnt,n,k,m;
int ans = 0;
bool cmp(zt a,zt b)
{
return a.v > b.v;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i ++)
{
scanf("%d%d",&x,&y);
if(x > m)ans += y;//面值大于指定钱数的钞票直接放
else{
B[++ cnt].v = x;
B[cnt].b = y;
}
}
sort(B + 1,B + cnt + 1,cmp);
while(1)
{
k = m;
for(int i = 1;i <= cnt;i ++)
if(B[i].v <= k && B[i].b)
{
int t = min(B[i].b,k/B[i].v);
B[i].b -= t;
k -= t * B[i].v;
}
if(k > 0)
{
for(int i = cnt;i >= 1;i --)
if(B[i].b && k > 0)
{
while(B[i].b && k > 0)
{
k -= B[i].v;
B[i].b --;
}
}
}
if(k > 0)break;
else ans ++;
}
printf("%d",ans);
}
T2
codevs2451互不侵犯
跟炮兵布阵那题好像……
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
#include<vector>
#define LL long long
using namespace std;
const int MAXN = 1000 + 50;
#define INF 1061109567
int gs[MAXN],tot,n,K,num[MAXN];
bool check(int x)
{
if((x << 1) & x)return false;
return true;
}
void init(int n)
{
for(int i = 0;i < (1 << n);i ++)
{
if(check(i))
{
gs[++ tot] = i;
for(int j = 0;(1 << j) <= i;j ++)
{
if((1 << j) & i)num[tot] ++;
}
}
}
}
LL dp[101][101][101];
long long ans;
int main()
{
freopen("Fking.in","r",stdin);
freopen("Fking.out","w",stdout);
scanf("%d%d",&n,&K);
init(n);
for(int i = 2;i <= tot;i ++)
{
for(int j = 0;j <= K;j ++)
dp[1][i][j] = -INF;
dp[1][i][num[i]] = 1;
}
dp[1][1][0] = 1;
for(int k = 2;k <= n;k ++)
{
for(int i = 1;i <= tot;i ++)
{
for(int j = 1;j <= tot;j ++)
{
if((gs[i] & (gs[j] << 1)) || (gs[i] & (gs[j] >> 1)) || (gs[i] & gs[j]))continue;
for(int t = num[j];t <= K;t ++)
{
//dp[k][j][t] = max(dp[k][j][t],dp[k - 1][i][t - num[j]] + 1);
if(dp[k - 1][i][t - num[j]] > 0)
dp[k][j][t] += dp[k - 1][i][t - num[j]];
//if(gs[j] == 0 && k == 2 && t == 1 && dp[k - 1][i][t - num[j]] == 1)printf("haha%d\n",gs[i]);
}
}
}
}
for(int i = 1;i <= tot;i ++)
if(dp[n][i][K] >= 0)
ans += dp[n][i][K];
/*for(int i = 1;i <= n;i ++)
for(int j = 1;j <= tot;j ++)
for(int k = 0;k <= K;k ++)
printf("i=%d,j=%d,k=%d,dp=%d\n",i,gs[j],k,dp[i][j][k]);
*/
printf("%lld",ans);
return 0;
}
T3
某校模拟赛原创题,很好玩的数据结构
题面
有一个含有 n 个数字的序列 A, 元素标号 1 到 n。
同时你有 n 个函数,标号为 1 到 n。
第 i 个函数函数值为序列中下标为 Li 到 Ri 的元素和。
现在你需要维护以下两种操作 1 x y : 将序列中下标为 x 的元素修改为 y2
s t : 询问标号为 s 到 t 的函数值的和
输入
第一行一个正整数 n,表示序列和函数的个数。
接下来一行 n 个整数表示序列 A。
接下来 n 行,每行两个整数 Li, Ri,表示第 i 个函数
接下来一行一个整数 q,表示询问次数
下面 q 行,每行一个询问,格式如题面描述
输出
对于每个询问 2, 输出对应答案
样例输入
5
1 2 3 4 5
1 3
2 5
4 5
3 5
1 2
4
2 1 4
1 3 7
2 1 4
2 3 5
样例输出
41
53
28
正解:
树状数组维护原序列前缀和
对函数分块,预处理出每块中函数和以及所有数字在每块中被覆盖次数←差分实现
这样单点修改的时候就可以 delta*(覆盖次数) 的算出每个块的改变值了
还有单点修改树状数组
查询时对于区间完全覆盖的块直接处理
否则利用树状数组暴力求出每个块外函数的值
细节上挺难处理的……尤其是分块那部分……
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define LL unsigned long long
#define lowbit(w) (w & (-w))
using namespace std;
const int MAXN = 100000 + 50;
int n,q;
struct zt
{
int l,r;
}f[MAXN];
int A[MAXN],x,y,ch;
struct kuai
{
LL sum;
}B[MAXN];
int cf[350][MAXN];
int sz;
int belong[MAXN];
LL c[MAXN];
LL ask(int w)
{
LL ans = 0;
while(w)
{
ans += c[w];
w -= lowbit(w);
}
return ans;
}
int num;
void add(int w,LL d)
{
while(w <= n)
{
c[w] += d;
w += lowbit(w);
}
}
int main()
{
freopen("sum.in","r",stdin);
freopen("sum.out","w",stdout);
scanf("%d",&n);
for(int i = 1;i <= n;i ++)
{
scanf("%d",&A[i]);
}
for(int i = 1;i <= n;i ++)
{
scanf("%d%d",&f[i].l,&f[i].r);
}
sz = sqrt(n) + 1;
num = (n - 1)/sz + 1;
for(int i = 1;i <= n;i ++)
{
belong[i] = (i - 1)/sz + 1;
}
for(int i = 1;i <= n;i ++)c[i] = A[i];
for(int i = 1;i <= n;i ++)
if(i + lowbit(i) <= n)
c[i + lowbit(i)] += c[i];
for(int i = 1;i <= n;i ++)
{
cf[belong[i]][f[i].l] ++;
cf[belong[i]][f[i].r + 1] --;
}
for(int i = 1;i <= num;i ++)
{
for(int j = 1;j <= n;j ++)
{
cf[i][j] += cf[i][j - 1];
B[i].sum += cf[i][j] * 1ULL * A[j];//
}
}
scanf("%d",&q);
for(int iii = 1;iii <= q;iii ++)
{
scanf("%d%d%d",&ch,&x,&y);
if(ch == 2)
{
int k1,k2;
k1 = belong[x];k2 = belong[y];
LL ans = 0;
if(k1 == k2)
{
for(int i = x;i <= y;i ++)
{
ans += ask(f[i].r) - ask(f[i].l - 1);
}
}
else
{
for(int i = k1 + 1;i < k2;i ++)
{
ans += B[i].sum;
}
int lim = sz * k1;
lim = min(lim,y);
for(int i = x;i <= lim;i ++)
ans += ask(f[i].r) - ask(f[i].l - 1);
lim = (k2 - 1)*sz + 1;
lim = max(lim,x);
for(int i = lim;i <= y;i ++)
{
ans += ask(f[i].r) - ask(f[i].l - 1);
}
}
printf("%llu\n",ans);//
}
else
{
for(int i = 1;i <= num;i ++)
{
B[i].sum -= cf[i][x] * 1ULL * A[x];
B[i].sum += cf[i][x] * 1ULL * y;
}
add(x,-A[x]);
A[x] = y;
add(x,A[x]);
}
}
fclose(stdin);
fclose(stdout);
return 0;
}
之前甚至听wyh大佬口胡过正解然而自己太辣鸡于是打次了……
这么辣鸡我怎么还不滚粗
T4
没看,没写