链接
分 = 7 、 > 7 、 < 7 =7、>7、<7 =7、>7、<7三种情况,对每一位为7其他位对此位的贡献进行计算
#include
using namespace std;
typedef long long ll;
#define IO ios::sync_with_stdio(false)
#define pb push_back
#define mk make_pair
const int N = 1e5+10;
const int mod = 1e9+7;
int t;
ll a[N];
string s;
ll p[N];
void init(){
p[0] = 1;
for(int i = 1; i < N; i++){
p[i] = p[i-1]*10%mod;
}
}
int main(){
IO;
cin >> t;
init();
while(t--){
cin >> s;
int n = s.size();
for(int i = 0; i < n; i++){
if(i == 0) a[i] = s[i]-'0';
else a[i] = (a[i-1]*10 + s[i] - '0') % mod;
}
ll ans = 0;
for(int i = n-1; i >= 0; i--){
ll l;
if(i == 0) l = 1;
else l = a[i-1] + 1;
ll r = (a[n-1] - a[i]*p[n-1-i]%mod + 1 + mod) % mod;
if(s[i] == '7'){
ans += r + (l-1+mod)%mod * p[n-1-i] % mod;
}
else if(s[i] > '7'){
ans += l * p[n-1-i] % mod;
}
else {
ans += (l-1+mod)%mod * p[n-1-i] % mod;
}
ans %= mod;
}
cout << ans << "\n";
}
return 0;
}
d p [ i ] [ j ] dp[i][j] dp[i][j] 前 i i i 位中选取若干数字后模 5 5 5 为 j j j 的最大值
#include
using namespace std;
typedef long long ll;
#define IO ios::sync_with_stdio(false)
#define pb push_back
#define mk make_pair
const int N = 1e6+10;
const int mod = 1e9+7;
int n, a[N];
ll dp[N][5];
int main(){
IO;
cin >> n;
for(int i = 1; i <= n; i++){
cin >> a[i];
}
dp[0][0] = 0;
for(int i = 0; i < n; i++){
for(int j = 0; j < 5; j++){
dp[i+1][j] = dp[i][j];
}
for(int j = 0; j < 5; j++){
if(dp[i][j]%5 == j){
dp[i+1][(j+a[i+1])%5] = max(dp[i+1][(j+a[i+1])%5], dp[i][j] + a[i+1]);
}
}
}
cout << dp[n][0] << "\n";
return 0;
}
d p [ i ] dp[i] dp[i] 表示影响 i i i 的所有开关的二进制表示, 使用bitset
使用拓扑排序进行 d p dp dp ,初始 d p [ 1 ] [ 1 ] = 1 dp[1][1] = 1 dp[1][1]=1, 从 u − > v u -> v u−>v , 首先影响 u u u的开关一定影响 v v v, 所以 d p [ v ] ∣ = d p [ u ] dp[v] |= dp[u] dp[v]∣=dp[u]
当 d [ v ] = = 0 d[v] == 0 d[v]==0 , 即影响v的点已经全部统计到 d p [ v ] dp[v] dp[v] 中,if 影响v的开关数量为奇数, 那么在这些开关的作用下,v打开( d p [ v ] . s e t ( v ) dp[v].set(v) dp[v].set(v) ),需要将v关闭( a n s + + ans++ ans++ )
#include
using namespace std;
typedef long long ll;
#define IO ios::sync_with_stdio(false)
#define pb push_back
#define mk make_pair
const int N = 4e4+10;
const int mod = 1e9+7;
int n, m;
vector<int> g[N];
int d[N], ans;
bitset<N> dp[N];
void tobo(){
queue<int> q;
for(int i = 1; i <= n; i++){
if(!d[i]){
q.push(i);
}
}
while(!q.empty()){
int u = q.front(); q.pop();
for(auto v:g[u]){
d[v]--;
dp[v] |= dp[u];
if(!d[v]){
if(dp[v].count()&1){
ans++;
dp[v].set(v);
}
q.push(v);
}
}
}
}
int main(){
IO;
cin >> n >> m;
int u, v;
for(int i = 0; i < m; i++){
cin >> u >> v;
g[u].push_back(v);
d[v]++;
}
ans = 1;
dp[1].set(1);
tobo();
cout << ans << "\n";
return 0;
}
筛出每个数因子和,再前缀和
#include
using namespace std;
typedef long long ll;
#define IO ios::sync_with_stdio(false)
#define pb push_back
#define mk make_pair
const int N = 1e6+10;
const int mod = 1e9+7;
int q, l, r;
ll p[N];
void init(){
p[1] = 1;
for(int i = 2; i < N; i++){
p[i] = i+1;
}
for(int i = 2; i < N; i++){
if(i > N/i) continue;
for(int j = i*i; j < N; j += i){
p[j] += i;
if(i != j/i){
p[j] += j/i;
}
}
}
for(int i = 2; i < N; i++){
p[i] += p[i-1];
}
}
int main(){
IO;
init();
cin >> q;
while(q--){
cin >> l >> r;
cout << p[r] - p[l-1] << "\n";
}
return 0;
}
先求出最小 ∑ ( a i ⊕ k ) ∑(a_i⊕k) ∑(ai⊕k) 和 此条件下最大的k,
然后从高位往低位贪心取, 求出最大的 k 。
#include
using namespace std;
typedef long long ll;
#define IO ios::sync_with_stdio(false)
#define pb push_back
#define mk make_pair
const int N = 1e5+10;
const int mod = 1e9+7;
int n, a[N], q, b[100];
ll m;
int main(){
IO;
cin >> n;
for(int i = 0; i < n; i++){
cin >> a[i];
for(int j = 0; j <= 30; j++){
if((a[i]>>j) & 1) b[j]++;
}
}
ll mn = 0; int k = 0;
for(int i = 0; i <= 30; i++){
mn += (1ll<<i)*min(b[i], n-b[i]);
if(b[i] >= n - b[i]) k |= (1<<i);
}
cin >> q;
while(q--){
cin >> m;
if(m < mn){
cout << "-1\n";
continue;
}
ll sum = mn, kk = k;
for(int i = 50; i >= 0; i--){
if((kk>>i) & 1) continue;
if(sum - (1ll<<i)*b[i] + (__int128)(1ll<<i)*(n-b[i]) <= m){
kk |= (1ll<<i);
sum = sum - (1ll<<i)*b[i] + (__int128)(1ll<<i)*(n-b[i]);
}
}
cout << kk << "\n";
}
return 0;
}
#include
using namespace std;
typedef long long ll;
#define IO ios::sync_with_stdio(false)
#define pb push_back
#define mk make_pair
const int N = 100+10;
const int mod = 1e9+7;
int n, a[N], p[N];
int main(){
IO;
cin >> n;
for(int i = 0; i < n; i++){
cin >> a[i];
}
for(int j = 0; j < n; j++){
cin >> p[j];
}
double ans = 0;
for(int i = 0; i < n; i++){
ans += p[i]*a[i];
}
ans = ans * 4 / 10000;
if(ans < 4.00+0.001 && ans > 4.00 - 0.001){
cout << "Yes\n";
}
else cout << "No\n";
return 0;
}
计算每个数字对答案的贡献
先看 s l , r = ∑ i = l r ∑ j = i r a i ∗ b j s_{l,r}=∑_{i=l}^r∑_{j=i}^ra_i*b_j sl,r=∑i=lr∑j=irai∗bj,令 i = 1,r = 1、2、3、… 、n
a 1 ∗ b 1 a_1*b_1 a1∗b1
a 1 ∗ ( b 1 + b 2 ) a_1*(b_1+b_2) a1∗(b1+b2)
…
a 1 ∗ ( b 1 + b 2 + . . . + b n ) a_1*(b_1+b_2+...+b_n) a1∗(b1+b2+...+bn)
可以得到,每个 b i b_i bi出现(n-i+1)次, b i = b i ∗ ( n − i + 1 ) b_i = b_i*(n-i+1) bi=bi∗(n−i+1), 求后缀和,
∑ l = 1 n ∑ r = l n s l , r ∑_{l=1}^n∑_{r=l}^ns_{l,r} ∑l=1n∑r=lnsl,r, 可以得到 a i ∗ b i a_i*b_i ai∗bi出现 i 次(求出后缀和后的 b i b_i bi);
所以答案为 ∑ a i ∗ b i ∗ i ∑a_i*b_i*i ∑ai∗bi∗i
#include
using namespace std;
typedef long long ll;
#define IO ios::sync_with_stdio(false)
#define pb push_back
#define mk make_pair
const int N = 1e6+10;
const int mod = 998244353;
int n;
ll a[N], b[N];
int main(){
IO;
cin >> n;
for(int i = 1; i <= n; i++){
cin >> a[i];
}
for(int i = 1; i <= n; i++){
cin >> b[i];
}
for(int i = n; i >= 1; i--){
b[i] = (b[i] * (n-i+1) % mod + b[i+1]) % mod;
}
ll ans = 0;
for(int i = 1; i <= n; i++){
ans = (ans + a[i]*b[i]%mod*i) % mod;
}
cout << ans << "\n";
return 0;
}
将方程化简可以得到 1 A = 4 ∑ i = l r a i c i \frac{1}{A} = 4\sum _{i=l}^ra_ic_i A1=4∑i=lraici, 线段树维护
#include
using namespace std;
typedef long long ll;
#define IO ios::sync_with_stdio(false)
#define pb push_back
#define mk make_pair
const int N = 1e5+10;
const int mod = 1e9+7;
int n, q, a[N];
ll sum[N*4];
void up(int o, int l, int r, int pos, int v){
if(l == r){
sum[o] += a[l] * v;
return ;
}
int mid = l+r>>1;
if(pos <= mid) up(o<<1, l, mid, pos, v);
else up(o<<1|1, mid+1, r, pos, v);
sum[o] = sum[o<<1] + sum[o<<1|1];
}
ll qu(int o, int l, int r, int ql, int qr){
if(ql <= l && qr >= r){
return sum[o];
}
ll res = 0;
int mid = l+r>>1;
if(mid >= ql) res += qu(o<<1, l, mid, ql, qr);
if(mid < qr) res += qu(o<<1|1, mid+1, r, ql, qr);
return res;
}
int main(){
IO;
cin >> n >> q;
for(int i = 1; i <= n; i++){
cin >> a[i];
}
int c;
for(int i = 1; i <= n; i++){
cin >> c;
up(1, 1, n, i, c);
}
int opt, l, r;
while(q--){
cin >> opt >> l >> r;
if(!opt){
up(1, 1, n, l, r);
}
else{
cout << 4*qu(1, 1, n, l, r) << "\n";
}
}
return 0;
}
求多源最短路,然后遍历每条边,当边上两点的距离大于边的长度时,找到火停的位置,取max
#include
using namespace std;
typedef long long ll;
#define IO ios::sync_with_stdio(false)
#define pb push_back
#define mk make_pair
const int N = 1e5+10;
const int mod = 1e9+7;
int n, m, s[N];
struct Edge{
int to, next, w;
}e[N*2];
int head[N], tot = 0;
void addEdge(int u, int v, int w){
e[tot] = (Edge){v, head[u], w};
head[u] = tot++;
}
priority_queue< pair<ll, int> > q;
int vis[N];
ll d[N];
void Dij(){
for(int i = 0; i <= n; i++){
d[i] = 1e18;
}
for(int i = 0; i <= m; i++){
d[s[i]] = 0;
q.push(mk(0, s[i]));
}
while(!q.empty()){
int u = q.top().second; q.pop();
if(vis[u]) continue;
vis[u] = 1;
for(int i = head[u]; i != -1; i = e[i].next){
int v = e[i].to;
if(d[v] > d[u] + e[i].w){
d[v] = d[u] + e[i].w;
q.push(mk(-d[v], v));
}
}
}
}
int main(){
IO;
cin >> n >> m;
memset(head, -1, sizeof(int)*(n+1));
int u, v, w;
for(int i = 0; i < n-1; i++){
cin >> u >> v >> w;
addEdge(u, v, w);
addEdge(v, u, w);
}
for(int i = 0; i < m; i++){
cin >> s[i];
}
Dij();
ll ans = 0;
int t1 = 1, t2 = 1;
for(int i = 1; i <= n; i++){
for(int j = head[i]; j != -1; j = e[j].next){
int v = e[j].to, w = e[j].w;
if(abs(d[i] - d[v] == w)) ans = max({ans, 2*d[v]});
else ans = max(ans, max(2*d[i], 2*d[v]) + (w-abs(d[i]-d[v])));
}
}
cout << ans << "\n";
return 0;
}
拆点限制流量的无向图最大流
#include
using namespace std;
typedef long long ll;
#define IO ios::sync_with_stdio(false)
#define pb push_back
#define mk make_pair
const int N = 400+10;
const int INF = 1e9;
const int mod = 1e9+7;
int n, m, s, t;
struct Edge{
int to, next, c, f;
}e[5000];
int head[N], tot = 0;
void addEdge(int u, int v, int c, int f){
e[tot] = (Edge){v, head[u], c, f};
head[u] = tot++;
}
int d[N];
int cur[N];
int bfs(){
memset(d,-1,(2*n+1) * sizeof(int));
queue<int>Q;
Q.push(s);
d[s] = 0;
while(!Q.empty())
{
int u = Q.front(); Q.pop();
for(int i = head[u]; i != -1; i = e[i].next)
{
int v = e[i].to;
if(d[v] == -1 && e[i].c > e[i].f)
{
d[v] = d[u] + 1;
if(v == t) return 1;
Q.push(v);
}
}
}
return 0;
}
int dfs(int u,int a){
if(u == t || a == 0)return a;
int flow = 0, f;
for(int &i = cur[u]; i != -1; i = e[i].next)
{
int v = e[i].to;
if(d[u]+1 == d[v] && ( f= dfs(v, min(a,e[i].c-e[i].f) ) ) > 0)
{
e[i].f += f;
e[i^1].f -= f;
flow += f;
a -= f;
if(a==0) break;
}
}
return flow;
}
ll Maxflow(){
ll flow = 0;
while(bfs())
{
for(int i = 1; i <= 2*n; i++){
cur[i] = head[i];
}
flow += dfs(s,INF);
}
return flow;
}
int main(){
IO;
cin >> n >> m;
memset(head, -1, sizeof(int)*(n*2+1));
int a;
for(int i = 1; i <= n; i++){
cin >> a;
addEdge(i, i+n, a, 0);
addEdge(i+n, i, 0, 0);
addEdge(i+n, i, a, 0);
addEdge(i, i+n, 0, 0);
}
int u, v, c;
for(int i = 1; i <= m; i++){
cin >> u >> v >> c;
addEdge(u+n, v, c, 0);
addEdge(v, u+n, 0, 0);
addEdge(v+n, u, c, 0);
addEdge(u, v+n, 0, 0);
}
int size;
cin >> s >> size;
t = 1;
cout << fixed << setprecision(6) << size*1.0/Maxflow() << "\n";
return 0;
}
sg[sta]表示某个子集的必胜/必败态
#include
using namespace std;
typedef long long ll;
#define IO ios::sync_with_stdio(false)
#define pb push_back
#define mk make_pair
const int N = 100+10;
const int mod = 1e9+7;
int n, x[N], y[N], X[N], Y[N];
int sg[1<<16];
int check(int a){
int cnt = 0;
for(int i = 0; i < n; i++){
if(a & (1<<i))
X[++cnt] = x[i], Y[cnt] = y[i];
}
if(cnt <= 2) return 1;
for(int i = 3; i <= cnt; i++){
if(1ll*(X[i]-X[1])*(Y[2]-Y[1]) != 1ll*(X[2]-X[1])*(Y[i]-Y[1])){
return 0;
}
}
return 1;
}
int dfs(int cur){
if(sg[cur] != -1) return sg[cur];
if(check(cur)){
return sg[cur] = 1;
}
for(int i = (cur-1)&cur; i; i = (i-1)&cur){
if(check(cur^i)==1 && dfs(i) == 0)
return sg[cur] = 1;
}
return sg[cur] = 0;
}
int main(){
IO;
cin >> n;
int m = 1 << n;
for(int i = 0; i < n; i++){
cin >> x[i] >> y[i];
}
memset(sg, -1, sizeof(sg));
sg[0] = 0;
if(dfs(m-1))
cout << "zyh\n";
else
cout << "fzj\n";
return 0;
}