题目链接

A. Charm Is Not Always Enough

模拟一下就可以了。

#include <bits/stdc++.h>
using namespace std; int T; int main() {
scanf("%d", &T);
while(T --) {
int n, m;
long long ans = 0;
scanf("%d%d", &n, &m);
while(n --) {
int x;
scanf("%d", &x);
x = x % m;
if(x == 0) continue;
ans = ans + 1LL * (m - x);
}
cout << ans << endl;
}
return 0;
}

B. Max and Alexis Plan to Conquer the World

打表。

设比例为$h$,可以发现$x$天之后的数量等于$n$乘上一个关于$h$的某种前缀和。

$h$只有$100$种,可以把每一种的前缀和都计算好,每组数据二分一下即可。

#include <bits/stdc++.h>
using namespace std; double h[105][4500]; void init() {
for(int i = 1; i <= 100; i ++) {
h[i][0] = 1.0;
for(int t = 1; t < 4500; t ++) {
h[i][t] = h[i][t - 1] + h[i][t - 1] * i / 100;
}
//printf("%lf\n", h[i][4499]);
}
} int main() {
init();
int T ;
scanf("%d", &T);
int cas = 1;
while(T -- > 0) {
double n;
scanf("%lf", &n);
int r;
scanf("%d", &r);
double p;
scanf("%lf", &p); int L = 0, R = 4499;
int ans = 0;
while(L <= R) {
int mid = (L + R) / 2;
if(n * h[r][mid] >= p) {
ans = mid;
R = mid - 1;
} else {
L = mid + 1;
}
}
printf("Case %d: %d\n", cas, ans);
cas ++;
}
}

C. Being Common is Too Mainstream

质因数分解,暴力。

#include <bits/stdc++.h>
using namespace std; //****************************************************************
// Miller_Rabin 算法进行素数测试
//速度快,而且可以判断 <2^63的数
//****************************************************************
const int S=20;//随机算法判定次数,S越大,判错概率越小 //计算 (a*b)%c. a,b都是long long的数,直接相乘可能溢出的
// a,b,c <2^63
long long mult_mod(long long a,long long b,long long c)
{
a%=c;
b%=c;
long long ret=0;
while(b)
{
if(b&1){ret+=a;ret%=c;}
a<<=1;
if(a>=c)a%=c;
b>>=1;
}
return ret;
} //计算 x^n %c
long long pow_mod(long long x,long long n,long long mod)//x^n%c
{
if(n==1)return x%mod;
x%=mod;
long long tmp=x;
long long ret=1;
while(n)
{
if(n&1) ret=mult_mod(ret,tmp,mod);
tmp=mult_mod(tmp,tmp,mod);
n>>=1;
}
return ret;
} //以a为基,n-1=x*2^t a^(n-1)=1(mod n) 验证n是不是合数
//一定是合数返回true,不一定返回false
bool check(long long a,long long n,long long x,long long t)
{
long long ret=pow_mod(a,x,n);
long long last=ret;
for(int i=1;i<=t;i++)
{
ret=mult_mod(ret,ret,n);
if(ret==1&&last!=1&&last!=n-1) return true;//合数
last=ret;
}
if(ret!=1) return true;
return false;
} // Miller_Rabin()算法素数判定
//是素数返回true.(可能是伪素数,但概率极小)
//合数返回false; bool Miller_Rabin(long long n)
{
if(n<2)return false;
if(n==2)return true;
if((n&1)==0) return false;//偶数
long long x=n-1;
long long t=0;
while((x&1)==0){x>>=1;t++;}
for(int i=0;i<S;i++)
{
long long a=rand()%(n-1)+1;//rand()需要stdlib.h头文件
if(check(a,n,x,t))
return false;//合数
}
return true;
} //************************************************
//pollard_rho 算法进行质因数分解
//************************************************
long long factor[100];//质因数分解结果(刚返回时是无序的)
int tol;//质因数的个数。数组小标从0开始 long long gcd(long long a,long long b)
{
if(a==0)return 1;//???????
if(a<0) return gcd(-a,b);
while(b)
{
long long t=a%b;
a=b;
b=t;
}
return a;
} long long Pollard_rho(long long x,long long c)
{
long long i=1,k=2;
long long x0=rand()%x;
long long y=x0;
while(1)
{
i++;
x0=(mult_mod(x0,x0,x)+c)%x;
long long d=gcd(y-x0,x);
if(d!=1&&d!=x) return d;
if(y==x0) return x;
if(i==k){y=x0;k+=k;}
}
}
//对n进行素因子分解
void findfac(long long n)
{
if(Miller_Rabin(n))//素数
{
factor[tol++]=n;
return;
}
long long p=n;
while(p>=n)p=Pollard_rho(p,rand()%(n-1)+1);
findfac(p);
findfac(n/p);
} const long long mod = 1000000001LL;
const int maxn = 1e5 + 10;
long long a[maxn];
vector<long long> fac[maxn]; bool prime(long long x) {
if(x == 1) return 0;
for(long long i = 2; i * i <= x; i ++) {
if(x % i == 0) return 0;
}
return 1;
} int main() {
srand(time(NULL));
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i ++) {
scanf("%lld", &a[i]);
}
long long ans = 1;
if(n == 1) {
ans = a[1] % mod;
} else if(n == 2) {
long long g = gcd(a[1], a[2]);
for(int i = 1; i <= n; i ++) {
a[i] /= g;
ans = ans * a[i] % mod;
}
} else if(n == 3) {
long long g;
g = gcd(a[1], gcd(a[2], a[3]));
for(int i = 1; i <= n; i ++) {
a[i] /= g;
}
g = gcd(a[1], a[2]);
a[1] /= g;
a[2] /= g;
g = gcd(a[2], a[3]);
a[2] /= g;
a[3] /= g;
g = gcd(a[1], a[3]);
a[1] /= g;
a[3] /= g;
for(int i = 1; i <= n; i ++) {
ans = ans * a[i] % mod;
}
} else if(n <= 1000) {
for(int i = 1; i <= n; i ++) {
if(a[i] == 1) continue;
tol = 0;
findfac(a[i]);
for(int j = 0; j < tol; j ++) {
fac[i].push_back(factor[j]);
}
}
for(int i = 1; i <= n; i ++) {
for(int j = 0; j < fac[i].size(); j ++) {
if(a[i] % fac[i][j]) continue;
int num = 0;
for(int k = 1; k <= n; k ++) {
if(a[k] % fac[i][j] == 0) num ++;
}
if(num < 2) continue;
for(int k = 1; k <= n; k ++) {
if(a[k] % fac[i][j] == 0) {
a[k] /= fac[i][j];
}
}
}
}
for(int i = 1; i <= n; i ++) {
ans = ans * a[i] % mod;
}
} else {
for(long long x = 2; x <= 601; x ++) {
if(!prime(x)) continue;
while(1) {
int num = 0;
for(int i = 1; i <= n; i ++) {
if(a[i] % x == 0) num ++;
}
if(num < 2) break;
for(int i = 1; i <= n; i ++) {
if(a[i] % x == 0) a[i] /= x;
}
}
}
for(int i = 1; i <= n; i ++) {
ans = ans * a[i] % mod;
}
}
printf("%lld\n", ans);
return 0;
} /*
10
1 2 3 4 5 6 7 8 9 10
*/

D. Shaat Chara

对于第$i$堆石头,要使得拿走第$i$堆的若干颗石头变成必胜态,也就是要使得剩下的所有石头异或和为$0$。

#include <bits/stdc++.h>
using namespace std; const long long mod = 1000000007LL;
const int maxn = 2e5 + 10;
int T, n;
int a[maxn]; int main() {
scanf("%d", &T);
int cas = 1;
while(T --) {
scanf("%d", &n);
int Xor = 0;
for(int i = 1; i <= n; i ++) {
scanf("%d", &a[i]);
Xor = Xor ^ a[i];
}
int ans = 0;
for(int i = 1; i <= n; i ++) {
Xor = Xor ^ a[i];
if(Xor < a[i]) ans ++;
Xor = Xor ^ a[i];
}
printf("Case %d: %d\n", cas ++, ans);
}
return 0;
}

E. Just One Swap

如果每个数字都不一样,答案就是$C_n^2$。

否则,相同的数字交换有$1$种情况,再计算不同数字交换的方案数。

#include <bits/stdc++.h>
using namespace std; const int maxn = 1e5 + 10;
int T;
int a[maxn]; int main() {
scanf("%d", &T);
while(T --) {
memset(a, 0, sizeof a);
int n;
scanf("%d", &n);
int y = n;
while(n --) {
int x;
scanf("%d", &x);
a[x] ++;
}
int ok = 1;
for(int i = 1; i <= 100000; i ++) {
if(a[i] > 1) ok = 0;
} long long ans = 0;
if(ok) {
ans = 1LL * y * (y - 1) / 2;
} else {
ans = 1LL;
long long sum = 0;
for(int i = 1; i <= 100000; i ++) {
ans = ans + sum * a[i];
sum = sum + a[i];
}
}
printf("%lld\n", ans);
}
return 0;
}

F. Halum and Candies

贪心,二分。

这题最直观的做法是每次将最大的$k$个数字减$1$,直到不能操作为止,但是在题目的数据规模下容易超时。

较为容易的写法是二分答案+验证,假设二分到$x$个人,只要看$\sum\limits_{i = 1}^n {\min (a[i],x)}$和$x*k$的大小关系即可。

#include <bits/stdc++.h>
using namespace std; int T, n, k;
const int maxn = 1e5 + 10;
long long a[maxn]; int check(long long x) {
long long p = 0;
for(int i = 1; i <= n; i ++) {
p = p + min(x, a[i]);
}
if(p >= x * k) return 1;
return 0;
} int main() {
int cas = 1;
scanf("%d", &T);
while(T --) {
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; i ++) {
scanf("%lld", &a[i]);
}
long long L = 0;
long long R = 1e12;
long long ans = 0;
while(L <= R) {
long long mid = (L + R) / 2;
if(check(mid)) ans = mid, L = mid + 1;
else R = mid - 1;
}
printf("Case %d: %lld\n", cas ++, ans);
}
return 0;
} /*
3
3 3
1 2 3
3 1
1 2 3
3 2
3 2 4
*/

G. XOR 'em all!

线段树。

每个节点存储每一种$1$的个数的最小的位置,以及转换后的即可。

#include <bits/stdc++.h>
using namespace std; const int maxn = 1e6 + 10;
int T, n, q;
int a[maxn], cnt[2 * maxn];
int s[maxn * 4][2][25];
int p[maxn * 4], f[maxn * 4];
int ans, B, v; int lowbit(int x) {
return x & (-x);
} void init() {
for(int i = 1; i < (1 << 20); i ++) {
cnt[i] = cnt[i - lowbit(i)] + 1;
}
} void pushUp(int rt) {
for(int i = 0; i < 21; i ++) {
s[rt][0][i] = min(s[2 * rt][p[2 * rt]][i],
s[2 * rt + 1][p[2 * rt + 1]][i]);
s[rt][1][i] = min(s[2 * rt][p[2 * rt] ^ 1][i],
s[2 * rt + 1][p[2 * rt + 1] ^ 1][i]);
}
p[rt] = 0;
} void pushDown(int rt) {
if(f[rt] == 0) return;
p[2 * rt] = (p[2 * rt] + f[rt]) % 2;
f[2 * rt] = (f[2 * rt] + f[rt]) % 2;
p[2 * rt + 1] = (p[2 * rt + 1] + f[rt]) % 2;
f[2 * rt + 1] = (f[2 * rt + 1] + f[rt]) % 2;
f[rt] = 0;
} void build(int l, int r, int rt) {
p[rt] = 0;
f[rt] = 0;
if(l == r) {
for(int t = 0; t < 2; t ++) {
for(int i = 0; i < 21; i ++) {
s[rt][t][i] = n + 1;
}
}
s[rt][0][a[l]] = l;
s[rt][1][20 - a[l]] = l;
return;
}
int mid = (l + r) / 2;
build(l, mid, 2 * rt);
build(mid + 1, r, 2 * rt + 1);
pushUp(rt);
} void update(int L, int R, int l, int r, int rt) {
if(L <= l && r <= R) {
p[rt] = (p[rt] + 1) % 2;
f[rt] = (f[rt] + 1) % 2;
return;
}
pushDown(rt);
int mid = (l + r) / 2;
if(L <= mid) update(L, R, l, mid, 2 * rt);
if(R > mid) update(L, R, mid + 1, r, 2 * rt + 1);
pushUp(rt);
} void query(int L, int R, int l, int r, int rt) {
if(L <= l && r <= R) {
for(int i = 0; i < 21; i ++) {
if(s[rt][p[rt]][i] > n) continue;
if(abs(i - v) < B) {
B = abs(i - v);
ans = s[rt][p[rt]][i];
} else if(abs(i - v) == B) {
ans = min(ans, s[rt][p[rt]][i]);
}
}
return;
}
pushDown(rt);
int mid = (l + r) / 2;
if(L <= mid) query(L, R, l, mid, 2 * rt);
if(R > mid) query(L, R, mid + 1, r, 2 * rt + 1);
pushUp(rt);
} int main() {
init();
scanf("%d", &T);
int cas = 1;
while(T --) {
printf("Case %d:\n", cas ++);
scanf("%d%d", &n, &q);
for(int i = 1; i <= n; i ++) {
scanf("%d", &a[i]);
a[i] = cnt[a[i]];
}
build(1, n, 1);
while(q --) {
int op, l, r;
scanf("%d%d%d", &op, &l, &r);
if(op == 1) {
scanf("%d", &v);
v = cnt[v];
B = 100;
ans = n + 1;
query(l, r, 1, n, 1);
printf("%d\n", ans);
} else {
update(l, r, 1, n, 1);
}
}
}
return 0;
} /*
1
10 9
47810 337106 289217 728190 763968 210307 934334 929186 401808 365768
2 8 10
1 2 10 611293
2 2 4
1 1 8 422298
2 6 8
2 2 10
1 5 6 180197
2 7 8
1 4 8 712158
*/

H. Simple Path

树形$dp$。

注意点:这题数据有问题,题面上说每条边都是从$u$到$v$的,但事实上不是。

#include <bits/stdc++.h>
using namespace std; const long long mod = 1000000007LL;
const int maxn = 4e5 + 10;
int T;
int h[maxn];
int v[maxn];
long long w[maxn];
int nx[maxn];
int n;
int sz[maxn];
long long ans;
int cnt;
int f[maxn]; void add(int a, int b, long long c) {
v[cnt] = b;
w[cnt] = c;
nx[cnt] = h[a];
h[a] = cnt ++;
} void SZ(int x) {
sz[x] = 1;
f[x] = 1;
for(int i = h[x]; i != -1; i = nx[i]) {
if(!f[v[i]]) {
SZ(v[i]);
sz[x] += sz[v[i]];
}
}
} void DP(int x, long long sum, int dep) {
f[x] = 1;
for(int i = h[x]; i != -1; i = nx[i]) {
if(f[v[i]]) continue;
// printf(" %d -> %d \n", x, v[i]);
long long A = 1LL * sz[v[i]] * sum % mod;
long long B = 1LL * sz[v[i]] * sz[v[i]] % mod;
B = 1LL * B * dep % mod;
long long C = (A - B + mod) % mod;
C = 1LL * C * w[i] % mod;
// cout << x << " debug " << C << endl;
ans = (ans + C) % mod;
long long G = 1LL * sz[v[i]];
G = (sum + G) % mod;
DP(v[i], G, dep + 1);
} //printf("debug %d %lld\n", x, dp[x]);
} int main() {
scanf("%d", &T);
int cas = 1;
while(T --) {
scanf("%d", &n);
cnt = 0;
for(int i = 1; i <= n; i ++) {
h[i] = -1;
sz[i] = 0;
f[i] = 0;
}
for(int i = 1; i < n; i ++) {
int a, b;
long long c;
scanf("%d%d%lld", &a, &b, &c);
add(a, b, c);
add(b, a, c);
}
SZ(1);
for(int i = 1; i <= n; i ++) {
if(sz[i] <= 0) while(1) {}
}
for(int i = 1; i <= n; i ++) {
f[i] = 0;
}
ans = 0;
DP(1, sz[1], 1);
printf("Case %d: %lld\n", cas ++, ans);
}
return 0;
} /*
2
7
1 2 3
1 3 2
2 4 1
2 5 4
3 6 6
3 7 8 6
1 2 3
1 3 2
1 4 4
3 5 7
3 6 1
*/

2017 Bangladesh National High School Programming Contest ( National Round, Senior Group ), NHSPC 2017 题解的更多相关文章

  1. Codeforces Gym101606 A.Alien Sunset (2017 United Kingdom and Ireland Programming Contest (UKIEPC 2017))

    2017 United Kingdom and Ireland Programming Contest (UKIEPC 2017) 寒假第一次组队训练赛,和学长一起训练,题目难度是3颗星,我和猪队友写 ...

  2. 2017 United Kingdom and Ireland Programming Contest (UKIEPC 2017)

    A. Alien Sunset 暴力枚举答案即可. #include<cstdio> int n,i,mx; struct P{ int h,r,t; bool night(int x){ ...

  3. 2017, X Samara Regional Intercollegiate Programming Contest 题解

    [题目链接] A - Streets of Working Lanterns - 2 首先将每一个括号匹配串进行一次缩减,即串内能匹配掉的就匹配掉,每个串会变成连续的$y$个右括号+连续$z$个左括号 ...

  4. 2019.04.11 第四次训练 【 2017 United Kingdom and Ireland Programming Contest】

    题目链接:  https://codeforces.com/gym/101606 A: ✅ B: C: ✅ D: ✅ https://blog.csdn.net/Cassie_zkq/article/ ...

  5. 2017 Wuhan University Programming Contest (Online Round) Lost in WHU 矩阵快速幂 一个无向图,求从1出发到达n最多经过T条边的方法数,边可以重复经过,到达n之后不可以再离开。

    /** 题目:Lost in WHU 链接:https://oj.ejq.me/problem/26 题意:一个无向图,求从1出发到达n最多经过T条边的方法数,边可以重复经过,到达n之后不可以再离开. ...

  6. 2017 Wuhan University Programming Contest (Online Round) C. Divide by Six 分析+模拟

    /** 题目:C. Divide by Six 链接:https://oj.ejq.me/problem/24 题意:给定一个数,这个数位数达到1e5,可能存在前导0.问为了使这个数是6的倍数,且没有 ...

  7. 2017 Wuhan University Programming Contest (Online Round) B Color 树形dp求染色方法数

    /** 题目:Color 链接:https://oj.ejq.me/problem/23 题意:给定一颗树,将树上的点最多染成m种颜色,有些节点不可以染成某些颜色.相邻节点颜色不同.求染色方法数. 思 ...

  8. [寒假集训第一场]gym101606 2017 United Kingdom and Ireland Programming Contest (UKIEPC 2017)

    3星场 难度在于英文题面太难读懂了QAQ 看样例猜题意的我 博客园的c++主题真丑 A Alien Sunset \(description\) 有\(n\)个星球,每个星球自转时间不一样,所以一天的 ...

  9. Codeforces Gym101606 C.Cued In (2017 United Kingdom and Ireland Programming Contest (UKIEPC 2017))

    C Cued In 这个题是打球的.都忘了写的什么了... 代码: 1 #include<iostream> 2 #include<cstring> 3 #include< ...

随机推荐

  1. Golang入门教程(一)GOPATH与工作空间(Windows)

    https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/01.2.md Windows 环境: 下面我就 ...

  2. RHEL-7.0重置root密码

    RHCE考试第一个环节就是重置root密码,然而7系列与6系列又存在着很大的不同.以下为RHEL-7.0系统对root密码重置的步骤! 1.开机出现引导菜单时按下e键    2.找到linux16行, ...

  3. Eclipse使用小结

    一.Eclipse新建工作空间设置默认编码格式UTF-8 1.windows->Preferences...打开"首选项"对话框,左侧导航树,导航到general->W ...

  4. angularJS $watch $apply $digest

    看O'Reilly的书看到$watch这部分,不过没看懂,网上很多资料也含糊不清,不过还是找到了几个好的,简单记录一下. 一句话说明,$watch是用来监视变量的,好了直接上代码 <html&g ...

  5. [译]Quartz.NET 框架 教程(中文版)2.2.x 之第五课 SimpleTrigger

    第五课 SimpleTrigger 如果你需要在一个指定时间段内执行一次作业任务或是在指定的时间间隔内多次执行作业任务,SimpleTrigger应该能满足你的调度需求.例如,你希望触发器在2015年 ...

  6. linux nginx服务 反向代理 负载均衡 nfs服务

    一.nginx服务 1.首先软件停用firewall #systemctl stop firewalld stop:本次停用 disable:开机停用 enable:开机启用 #ps aux | gr ...

  7. 【leetcode 简单】 第一百一十题 分发饼干

    假设你是一位很棒的家长,想要给你的孩子们一些小饼干.但是,每个孩子最多只能给一块饼干.对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸:并且每块饼干 j ,都有一个尺寸 ...

  8. 去除zabbix calculate 模式下,有时候分母为零的情况(Cannot evaluate expression: division by zero. )

    zabbix的监控类型支持一种calculate的方式,可以对几个item结果进行简单的计算,但有时会出现分母为零的情况,这时候监控项就会报错 Cannot evaluate expression: ...

  9. 常见踩坑案例(二)-Request method 'POST' not supported

    一 前言 最近涉及到与前后端的数据对接,按道理来说没一点压力结果被一前端童鞋带坑里去了(不过也是很久没写过这种前后端分离进行联调的事情了,如果是一个人全套弄的话就不会出现下面问题). 二 Reques ...

  10. Multiple HTTPS Bindings IIS 7 Using appcmd

    http://toastergremlin.com/?p=308 Sometimes when using a wildcard SSL or Unified Communications Certi ...