目录
[1001 ^&^]
1002 array
1003 K-th occurrence
1004 path
1005 huntian oy
1006 Shuffle Card
1007 Windows Of CCPC
1008 Fishing Master
1009 Kaguya
1010 Touma Kazusa's function
1011 sakura
1005 huntian oy
队友知道后面那串东西当a,b互质的时候就是i-j,那么变成求 \(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{i}(i-j)[gcd(i,j)==1]\) 。
要求:
\(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{i}(i-j)[gcd(i,j)==1]\)
很明显把i提前:
\(\sum\limits_{i=1}^{n}i\varphi(i)\space - \space \sum\limits_{j=1}^{i}j[gcd(i,j)==1]\)
后面那个是求:
\(\sum\limits_{i=1}^{n}i[gcd(i,n)==1]\)
显然:
\(\sum\limits_{i=1}^{n}i[gcd(i,n)==1] = \frac{n}{2}([n==1]+\varphi(n))\)
代进去得到:
\(\sum\limits_{i=1}^{n}i\varphi(i) - \frac{i}{2}([i==1]+\varphi(i))\)
即:
\(-\frac{1}{2}+\frac{1}{2}\sum\limits_{i=1}^{n}i\varphi(i)\)
这个是卷个g=id就可以得到了。
写得太豪放了差点T了,收敛一点的话还是很稳的。
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int mod = 1e9 + 7;
int qpow(ll x, int n) {
ll res = 1;
while(n) {
if(n & 1)
res = res * x % mod;
x = x * x % mod;
n >>= 1;
}
return res;
}
const int inv2 = (mod + 1) >> 1;
const int inv6 = qpow(6, mod - 2);
const int MAXN = pow(1e9, 2.0 / 3.0);
int pri[MAXN + 10], pritop;
int pk[MAXN + 10];
ll sum[MAXN + 10];
void sieve(int n = MAXN) {
sum[1] = 1;
pk[1] = 1;
for(int i = 2; i <= n; i++) {
if(!pk[i]) {
pri[++pritop] = i;
pk[i] = i;
sum[i] = 1ll * i * (i - 1);
if(sum[i] >= mod)
sum[i] %= mod;
}
for(int j = 1, t; j <= pritop && (t = i * pri[j]) <= n; j++) {
if(i % pri[j]) {
pk[t] = pk[pri[j]];
sum[t] = sum[i] * sum[pri[j]] ;
if(sum[t] >= mod)
sum[t] %= mod;
} else {
pk[t] = pri[j] * pk[i];
if(t == pk[t]) {
sum[t] = 1ll * t * (t - t / pri[j]) ;
if(sum[t] >= mod)
sum[t] %= mod;
} else {
sum[t] = sum[pk[t]] * sum[t / pk[t]] ;
if(sum[t] >= mod)
sum[t] %= mod;
}
break;
}
}
}
for(int i = 2; i <= n; i++) {
sum[i] += sum[i - 1];
if(sum[i] >= mod)
sum[i] -= mod;
}
}
inline int s1(int n) {
ll t = (1ll * n * (n + 1)) >> 1;
if(t >= mod)
t %= mod;
return t;
}
inline int s2(ll n) {
ll t = n * (n + 1ll);
if(t >= mod)
t %= mod;
t *= inv6;
if(t >= mod)
t %= mod;
t *= (2ll * n + 1ll);
if(t >= mod)
t %= mod;
return t;
}
unordered_map<int, int> Sum;
//杜教筛
inline int GetSum(int n) {
if(n <= MAXN)
return sum[n];
else if(Sum.count(n))
return Sum[n];
//f*g=id的前缀和
ll ret = s2(n);
for(int l = 2, r; l <= n; l = r + 1) {
r = n / (n / l);
ll tmp = (s1(r) - s1(l - 1));
if(tmp < 0)
tmp += mod;
tmp *= GetSum(n / l);
if(tmp >= mod)
tmp %= mod;
ret -= tmp;
if(ret < 0)
ret += mod;
}
return Sum[n] = ret; // 记忆化
}
inline int Ans(int n) {
ll tmp = GetSum(n) - 1;
if(tmp < 0)
tmp += mod;
tmp *= inv2;
if(tmp >= mod)
tmp %= mod;
return tmp;
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
sieve();
int t;
scanf("%d", &t);
while(t--) {
int n, a, b;
scanf("%d%d%d", &n, &a, &b);
printf("%d\n", Ans(n));
}
}
1006 Shuffle Card
一个非常搞的签到题,一开始以为要用个Treap去手写一些结构,写到Remove的时候一想不是用个set就可以了吗?
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
set<pair<int, int> > s;
int p[100005];
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) {
int ai;
scanf("%d", &ai);
p[ai] = i;
s.insert({p[ai], ai});
}
int cur = 0;
for(int i = 1; i <= m; ++i) {
int ai;
scanf("%d", &ai);
s.erase({p[ai], ai});
p[ai] = cur--;
s.insert({p[ai], ai});
}
for(auto si : s) {
printf("%d ", si.second);
}
}