题目链接

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. python学习笔记2-文件操作

    一.文件操作 #文件操作一定要注意文件指针 f=open('','a+,encoding=utf-8) f.seek(0) #文件指针移到行首 f.tell()#查看文件指针的位置 f.read()# ...

  2. Mycat从入门到放弃

    https://blog.csdn.net/u013235478/article/details/53178657

  3. LintCode 58: Compare Strings

    LintCode 58: Compare Strings 题目描述 比较两个字符串A和B,确定A中是否包含B中所有的字符.字符串A和B中的字符都是大写字母. 样例 给出A = "ABCD&q ...

  4. SQL Server DB Link相关

    若想通过DBlink 清空表或执行存储过程,可以通过这种方式 Insert into table select * from table时,Pull 方式比Push方式快很多

  5. 截取汉字 mb_sbstr()

    一.中文截取:mb_substr() mb_substr( $str, $start, $length, $encoding ) $str,需要截断的字符串 $start,截断开始处,起始处为0 $l ...

  6. vue_列表渲染

    vue列表渲染 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <t ...

  7. 【译】第六篇 SQL Server代理深入作业步骤工作流

    本篇文章是SQL Server代理系列的第六篇,详细内容请参考原文. 正如这一系列的前几篇所述,SQL Server代理作业是由一系列的作业步骤组成,每个步骤由一个独立的类型去执行.每个作业步骤在技术 ...

  8. ubuntu安装Android Studio开发环境

    1.下载 https://developer.android.com/studio/ 2.解压文件,将文件夹copy到/opt/ 3.进入/opt/android-studio/bin,运行./stu ...

  9. Find Minimum in Rotated Sorted Array I & II

    Find Minimum in Rotated Sorted Array I Suppose a sorted array is rotated at some pivot unknown to yo ...

  10. Docker中安装wiki Confluence

    一下内容在centos 7安装成功. 一.安装docker 1.yum安装docker yum update # 更新yum yum install docker # yum安装docker 2.开启 ...