CNT = 9
太弱了只会跟着别人的list刷水题T_T
【bzoj2818】
sb欧拉函数题
gcd(x,y)==p <=> gcd(x/p,y/p)==1
然后就是枚举素数算一算phi(n/p)
#include
#define For(i,a,b) for(int i=a;i<=b;i++)
typedef long long ll;
ll phi[10000001];
int pri[1000001], vis[10000001];
int n , tot;
inline void calc_phi() {
For(i , 2 , n) {
if (!vis[i]) pri[++ tot] = i , phi[i] = i - 1;
For(j , 1 , tot) if ((ll) pri[j] * i > n) break;
else {
int t = i * pri[j];
vis[t] = 1;
if (i % pri[j] == 0) { phi[t] = phi[i] * pri[j] ; break ; }
else phi[t] = phi[i] * (pri[j] - 1);
}
}
}
int main() {
scanf("%d" , &n);
calc_phi();
For(i , 2 , n) phi[i] += phi[i - 1];
ll ans = 0;
For(i , 1 , tot) ans += 2 * phi[n / pri[i]] + 1;
printf("%lld\n" , ans);
return 0;
}
【bzoj2190】
还是sb欧拉函数题
写的时候忘记边界phi[1]=1了调了好久……弱的不行
显然一个点(x,y)能被看到当且仅当gcd(x,y)==1
也就是说题目要统计 ∑1<=i,j<=n−1[gcd(i,j)==1]
欧拉函数像上一题那样随便搞搞就行了
#include
#define For(i,a,b) for(int i=a;i<=b;i++)
typedef long long ll;
int vis[65535] , pri[8191] , phi[65535] , n , tot;
void init() {
phi[1] = 1;
For(i , 2 , n) {
if (!vis[i]) pri[++ tot] = i , phi[i] = i - 1;
for(int j = 1 ; j <= tot && pri[j] * i <= n ; j ++) {
int t = pri[j] * i;
vis[t] = 1;
if (i % pri[j] == 0) { phi[t] = phi[i] * pri[j] ; break ; }
else phi[t] = phi[i] * (pri[j] - 1);
}
}
}
int main() {
scanf("%d" , &n);
init();
ll ans = 1;
For(i , 1 , n - 1) ans += (ll) 2 * phi[i];
printf("%lld\n" , ans);
return 0;
}
【bzoj1257】
小学奥数经常会碰到的奇怪的东西!
∑1<=j<=nk mod j=∑1<=j<=n(k−⌊kj⌋∗j)
注意到 ⌊kj⌋ 这个东西取值大部分是一样的所以直接枚举这个东西然后乱搞统计。
#include
typedef long long ll;
int n , k;
int main() {
scanf("%d%d" , &n , &k);
ll ans = (ll)n * k;
if (n > k) n = k;
for(int i = 1 , j , l , r;i <= n;i = r + 1) {
j = k / i;
l = k / (j + 1) + 1 , r = std::min(k / j , n);
ans -= (ll) (l + r) * (r - l + 1) / 2 * j;
}
printf("%lld\n" , ans);
return 0;
}
【bzoj2761】
看到有人这题PE了就随手写了一发
然后也PE了T_T
注意输出格式!!!!!
每一行不能有多余空格回车等字符!!!
第一个数输出前无空格,后面每一个输出的数前面加一个空格
然后也是水题……
交了三次T_T
#include
using namespace std;
#define For(i,a,b) for(int i=a;i
#define maxn 65535
inline int rd() {
char c = getchar();
while (!isdigit(c) && c != '-') c = getchar() ; int x = 0 , f = 1;
if (c == '-') f = -1; else x = c - '0';
while (isdigit(c = getchar())) x = x * 10 + c - '0';
return x * f;
}
int a[maxn] , b[maxn] , c[maxn];
int n;
map<int , int> s;
void input() {
s.clear();
n = rd();
For(i , 0 , n) if (s.find(a[i] = rd()) == s.end()) s[a[i]] = i;
For(i , 0 , n) c[i] = 0;
}
void solve() {
for(map<int , int>::iterator it = s.begin() ; it != s.end() ; it ++) b[it -> second] = it -> first , c[it -> second] = 1;
printf("%d" , b[0]);
For(i , 1 , n) if (c[i]) printf(" %d" , b[i]);
}
int main() {
int T = rd();
while (T --) {
input();
solve();
if (T) puts("\0");
}
return 0;
}
【bzoj3209】
弱得不行,调了1h+ T_T
求 ∑1<=k<=nbitscount(k)
注意到二进制位的个数只有那么多个,于是枚举二进制位1的个数,然后用类似数位DP的东西乱搞统计。
比如说现在要t个1,枚举到了(从右往左)第i位,现在的贡献就是 (i−1t) ,所以就一路加起来。
#include
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
typedef long long ll;
const int mod = 10000007;
int a[65] , l , s[65];
ll n , c[65][65];
ll Pow(ll a , ll b) {
ll ret = 1;
while (b) {
if (b & 1) ret = ret * a % mod;
a = a * a % mod , b >>= 1;
}
return ret;
}
void init() {
for(ll t = n + 1;t;t >>= 1) a[++ l] = (t & 1);
c[0][0] = 1;
rep(i , 1 , l + 1) {
c[i][0] = 1;
rep(j , 1 , i) c[i][j] = c[i - 1][j] + c[i - 1][j - 1];
}
}
inline ll calc(int t) {
ll ret = 0;
per(i , l , 1) if (a[i]) {
ret += c[i - 1][t --];
if (t < 0) break;
}
return ret;
}
void solve() {
ll ans = 1;
rep(i , 1 , l) ans = ans * Pow(i , calc(i)) % mod;
printf("%lld\n" , ans);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.txt" , "r" , stdin);
freopen("data.out" , "w" , stdout);
#endif
scanf("%lld" , &n);
init();
solve();
return 0;
}
【bzoj1468】
点分经典裸题(刷题量T_T)
10min写完蛤蛤蛤蛤
#include
using namespace std;
#define For(i,a,b) for(int i=a;i
#define fore(i,u) for(int i=head[u];i;i=nxt[i])
#define maxn 100007
inline int rd() {
char c = getchar();
while (!isdigit(c)) c = getchar() ; int x = c - '0';
while (isdigit(c = getchar())) x = x * 10 + c - '0';
return x;
}
typedef int arr[maxn];
arr to , val , nxt , head , fa , vis , dis , sz , mx;
int n , ett , K , mn , rt , ans , tot;
inline void ins(int w , int u , int v) {
to[++ ett] = v , val[ett] = w , nxt[ett] = head[u] , head[u] = ett;
to[++ ett] = u , val[ett] = w , nxt[ett] = head[v] , head[v] = ett;
}
inline void upmax(int&a , int b) { if (a < b) a = b ; }
void input() {
n = rd();
For(i , 1 , n) ins(rd() , rd() , rd());
K = rd();
}
#define ok (v != fa && !vis[v])
void dfs_size(int u , int fa) {
sz[u] = 1;
fore(i , u) {
int v = to[i];
if (!ok) continue;
dfs_size(v , u);
sz[u] += sz[v] , upmax(mx[u] , sz[v]);
}
}
void dfs_root(int r , int u , int fa) {
upmax(mx[u] , sz[r] - sz[u]);
if (mx[u] < mn) rt = r , mn = mx[u];
fore(i , u) {
int v = to[i];
if (!ok) continue;
dfs_root(r , v , u);
}
}
void dfs_dis(int u , int fa , int w) {
dis[tot ++] = w;
fore(i , u) {
int v = to[i];
if (!ok) continue;
dfs_dis(v , u , w + val[i]);
}
}
int calc(int u , int d) {
int ret = 0; tot = 0;
dfs_dis(u , 0 , d);
sort(dis , dis + tot);
for(int i = 0 , j = tot - 1 ; i < j ; i ++) {
while (dis[i] + dis[j] > K && i < j) j --;
ret += j - i;
}
return ret;
}
void dfs(int u) {
mn = n;
dfs_size(u , 0);
dfs_root(u , u , 0);
vis[rt] = 1 , ans += calc(rt , 0);
fore(i , rt) {
int v = to[i];
if (vis[v]) continue;
ans -= calc(v , val[i]);
dfs(v);
}
}
void solve() {
dfs(1);
printf("%d\n" , ans);
}
int main() {
input();
solve();
return 0;
}
【bzoj3207】
孟爷的题,题意大坑。。
给一个序列,有m次询问,每次询问一个长度为K的序列是否在某个区间内出现过。
子串不是子序列!
差不多就是GSS系列,只不过问的是长度为K的串。既然是串哈希一下就OK,偷懒用了 O(nk) 的哈希似乎也没有问题……
数据范围有点大,就可持久化咯。
一开始哈希是unsigned就想搞可持久化trie……不过其实把哈希值离散化一下就可以了。
#include
using namespace std;
#define For(i,a,b) for(int i=a;i<=b;i++)
#define maxm 2097151
#define maxn 131071
#define P 107
typedef long long ll;
typedef unsigned long long ull;
typedef mapint >::iterator iter;
typedef int seg[maxm];
typedef int arr[maxn];
mapint > ord;
arr a , rt;
seg lc , rc , sz;
int n , m , K , tot;
ull h[maxn];
inline int rd() {
char c = getchar();
while (!isdigit(c) && c != '-') c = getchar() ; int x = 0 , f = 1;
if (c == '-') f = -1 ; else x = c - '0';
while (isdigit(c = getchar())) x = x * 10 + c - '0';
return x * f;
}
inline ull Hash(int*a) {
ull ret = 0;
For(i , 0 , K - 1) {
ret *= P;
ret += a[i];
}
return ret;
}
void update(int pr , int&nr , int l , int r , int v) {
sz[nr = ++ tot] = sz[pr] + 1;
if (l == r) return;
int m = (l + r) >> 1;
lc[nr] = lc[pr] , rc[nr] = rc[pr];
if (v < m) update(lc[pr] , lc[nr] , l , m , v);
else update(rc[pr] , rc[nr] , m + 1 , r , v);
}
int query(int pr , int nr , int l , int r , int v) {
if (l == r) return sz[nr] - sz[pr];
int m = (l + r) >> 1;
if (v < m) return query(lc[pr] , lc[nr] , l , m , v);
else return query(rc[pr] , rc[nr] , m + 1 , r , v);
}
void input() {
n = rd() , m = rd() , K = rd();
For(i , 1 , n) a[i] = rd();
For(i , 1 , n - K + 1) {
h[i] = Hash(a + i);
ord[h[i]] = i;
}
ull t = 0;
for(iter it = ord.begin();it != ord.end();it ++)
it -> second = t ++;
For(i , 1 , n) {
t = ord[h[i]];
update(rt[i - 1] , rt[i] , 0 , n , t);
}
}
void solve() {
while (m --) {
int l = rd() , r = rd();
For(i , 1 , K) a[i] = rd();
ull t = Hash(a + 1);
if (ord.find(t) == ord.end()) {
puts("Yes");
continue;
}
int k = ord[t];
int ans = query(rt[l - 1] , rt[r] , 0 , n , k);
puts(ans ? "No" : "Yes");
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.txt" , "r" , stdin);
#endif
input();
solve();
return 0;
}
【bzoj3208】
还是孟爷的题,不过是良心大水题√
经典DP的“动态版”,然而动态并没有什么卵用,闷声大暴力就可以了2333
#include
#define For(i,a,b) for(int i=a;i<=b;i++)
const int fx[] = {0 , 0 , 1 , -1};
const int fy[] = {1 , -1 , 0 , 0};
typedef int mat[707][707];
mat h , s , f;
int n , m;
void input() {
scanf("%d" , &n);
For(i , 1 , n) For(j , 1 , n) scanf("%d" , &h[i][j]);
scanf("%d" , &m);
For(i , 1 , n) s[i][0] = s[i][n + 1] = s[n + 1][i] = s[0][i] = 1;
}
inline void upmax(int&a , int b) { if (a < b) a = b ; }
inline void cover(int a , int b , int c , int d , int v) {
For(i , a , c) For(j , b , d) s[i][j] = v;
}
int dp(int x , int y) {
if (f[x][y] != -1) return f[x][y];
int ret = 0;
For(i , 0 , 3) {
int nx = x + fx[i] , ny = y + fy[i];
if (s[nx][ny]) continue;
if (h[nx][ny] >= h[x][y]) continue;
upmax(ret , dp(nx , ny));
}
return f[x][y] = ret + 1;
}
inline void query() {
int ans = 0;
For(i , 1 , n) For(j , 1 , n) f[i][j] = -1;
For(i , 1 , n) For(j , 1 , n) if (f[i][j] == -1 && !s[i][j]) dp(i , j);
For(i , 1 , n) For(j , 1 , n) upmax(ans , f[i][j]);
printf("%d\n" , ans) ;
}
void solve() {
while (m --) {
char cmd[10];
int a , b , c , d;
scanf("%s" , cmd);
if (cmd[0] == 'Q') {
query();
continue;
}
scanf("%d%d%d" , &a , &b , &c);
if (cmd[0] == 'C') {
h[a][b] = c;
continue;
}
scanf("%d" , &d);
cover(a , b , c , d , cmd[0] == 'S');
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.txt" , "r" , stdin);
#endif
input();
solve();
return 0;
}
【bzoj1083】
生成树超级大水题
然而看错数据范围狂WA 7发QAQ
#include
using namespace std;
#define For(i,a,b) for(int i=a;i
#define Dwn(i,a,b) for(int i=a-1;i>=b;i--)
#define maxn 100001
inline int rd() {
char c = getchar();
while (!isdigit(c)) c = getchar() ; int x = c - '0';
while (isdigit(c = getchar())) x = x * 10 + c - '0';
return x;
}
struct node {
int u , v , c;
node(int u = 0 , int v = 0 , int c = 0):u(u) , v(v) , c(c) { }
}e[maxn];
int n , m , tot , fa[maxn];
bool cmp(const node a , const node b)
{ return a.c < b.c; }
void input() {
n = rd() , m = rd();
For(i , 0 , m) e[i].u = rd() , e[i].v = rd() , e[i].c = rd();
sort(e , e + m , cmp);
}
int find(int u)
{ return u == fa[u] ? u : fa[u] = find(fa[u]) ; }
bool ok(int x) {
tot = 1;
For(i , 1 , n + 1) fa[i] = i;
fa[find(e[x].u)] = find(e[x].v);
Dwn(i , x , 0) {
int u = find(e[i].u) , v = find(e[i].v);
if (u == v) continue;
fa[u] = v , tot ++;
}
return tot == n - 1;
}
void solve() {
For(i , 0 , m) if (ok(i))
{ printf("%d %d\n" , n - 1 , e[i].c) ; return ; }
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.txt" , "r" , stdin);
#endif
input();
solve();
return 0;
}