暑假第十三测
Posted edsheeran
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了暑假第十三测相关的知识,希望对你有一定的参考价值。
题解:
第一题:
规律可由打表知,需要注意一下容斥原理
#include<bits/stdc++.h> using namespace std; const int M = 1e4 + 10; #define ll long long int n; ll m, Ans, num[M], vis[M]; ll a[M], qs[M]; ll gcd(ll a, ll b){ if(!b)return a; return gcd(b, a%b); } int main(){ freopen("a.in","r",stdin); freopen("a.out","w",stdout); int T, pp =0; scanf("%d", &T); while(T--){ pp++; int fg = 0, cnt = 0; Ans = 0; memset(vis, 0, sizeof(vis)); memset(num ,0, sizeof(num)); scanf("%d%I64d", &n, &m); for(int i = 1; i * i <= m; i++){ if(m % i == 0){ qs[++cnt] = i; if(i * i != m)qs[++cnt] = m/i; } } sort(qs+1, qs+1+cnt); for(int i = 1; i <= n; i++){ scanf("%I64d", &a[i]); a[i] = gcd(m, a[i]); for(int j = 1; j <= cnt; j++){ if(qs[j] % a[i] == 0)vis[j] = 1; } } for(int i = 1; i <= cnt; i++){ if(vis[i] == num[i])continue; ll kk = (m - 1) / qs[i]; ll tmp = (kk + 1) * qs[i] * kk / 2; Ans += tmp*(vis[i] - num[i]); // printf("%I64d %d %I64d ",Ans, qs[i], vis[i] - num[i]); for(int j = i + 1; j <= cnt; j++) if(qs[j] % qs[i] == 0) num[j] += vis[i] - num[i]; } printf("Case #%d: %I64d ",pp, Ans); } }
第二题:二进制数位dp, 拆数成二进制,枚举1的个数,最后满足 余数=0 && 该数中出现的1的个数 = 枚举的1的个数
这道题要开unsigned long long ,我开始memset dp -1, 交上去全对,看来没有用到记忆画搜索???反正很玄学就是了
#include<bits/stdc++.h> using namespace std; #define ll unsigned long long ll dp[73][73][73], bin[72]; int digit[73]; bool vis[73][73][73]; ll dfs(int dep, int f, int yu, int sum, int ss){ if(!dep){ return !yu && sum == ss; } if(vis[dep][yu][sum] && !f)return dp[dep][yu][sum]; ll tmp = 0; int i = f ? digit[dep] : 1; for(; i >= 0; i--){ tmp += dfs(dep -1, f & (i == digit[dep]), (yu + i * bin[dep] % ss )% ss, sum + (i == 1), ss); } vis[dep][yu][sum] = 1; if(!f) dp[dep][yu][sum] = tmp; return tmp; } ll get(ll n){ ll ans = 0; int cnt = 0; while(n){ digit[++cnt] = n%2; n /= 2; } for(int i = 1; i <= 71; i++){ memset(vis, 0, sizeof(vis)); ans += dfs(cnt, 1, 0, 0, i); } return ans; } int main(){ //freopen("b.in","r",stdin); //freopen("b.out","w",stdout); ll n; bin[1] = 1; for(int i = 2; i <= 71; i++) bin[i] = bin[i - 1] << 1; scanf("%I64dd", &n); ll ans = get(n); printf("%I64d ", ans); }
第三题:
这个做法很巧妙啊~
#include<bits/stdc++.h> using namespace std; #define ll long long const int M = 1005; ll l[M], h[M], a[M][M], ansx[M], ansy[M]; int main(){ freopen("c.in","r",stdin); freopen("c.out","w",stdout); int n, m; scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++){ scanf("%I64d", &a[i][j]); l[j] += a[i][j]; h[i] += a[i][j]; } for(int i = 0; i <= n; i++){ ll x = 2; for(int j = i; j; j--, x += 4) ansx[i] += h[j] * x * x; x = 2; for(int j = i + 1; j <= n; j++, x += 4) ansx[i] += h[j] * x * x; } for(int i = 0; i <= m; i++){ ll x = 2; for(int j = i; j; j--, x += 4) ansy[i] += l[j] * x * x; x = 2; for(int j = i + 1; j <= m; j++, x += 4) ansy[i] += l[j] * x * x; } ll Ans = 1e18; int x, y; for(int i = 0; i <= n; i++) for(int j = 0; j <= m; j++) if(ansx[i] + ansy[j] < Ans) Ans = ansx[i] + ansy[j], x = i, y = j; printf("%I64d %d %d ", Ans, x, y); }
以上是关于暑假第十三测的主要内容,如果未能解决你的问题,请参考以下文章