A:题意:n个格子排成一排,每个a[i],要求重排成k个,每个人数相同,合并两个和划分成两个(可以不等)都是花费为1,问最小花费
题解:从前往后贪心即可,由于哪个地方忘开ll,wa了,全改成ll就过了
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
//#pragma comment(linker, "/stack:200000000") //#pragma GCC optimize("Ofast,no-stack-protector") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") //#pragma GCC optimize("unroll-loops") #include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pi acos(-1.0) #define ll long long #define vi vector<int> #define mod 1000000007 #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pli pair<ll,int> #define pii pair<int,int> #define cd complex<double> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double eps=1e-6; const int N=100000+10,maxn=5000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; ll a[N],n,k; void solve(ll x) { ll ans=0,res=0; for(int i=1;i<=n;i++) { if(res!=0)ans++,a[i]+=res; if(a[i]>=x) { ll te=a[i]/x; if(a[i]%x==0)te--; ans+=te; res=a[i]%x; } else res=a[i]; } printf("%lld\n",ans); } int main() { int T;scanf("%d",&T); for(int _=1;_<=T;_++) { scanf("%lld%lld",&n,&k); ll sum=0; for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); sum+=a[i]; } printf("Case #%d: ",_); if(sum%k!=0)puts("-1"); else solve(sum/k); } return 0; } /******************** ********************/
B:题意:n个炸弹,引爆需要花费,引爆后会引爆范围内的炸弹,问最小花费
题解:强连通缩点求dag上度数最小的点,(队友写的,细节不清楚)
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int,int> #define piii pair<int,pair<int,int>> using namespace std; const int N = 1000 + 7; const int M = 1e4 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; int n, idx, top, cnt, id[N], dfn[N], st[N], low[N], deg[N]; LL cost[N]; bool in[N]; struct Point { LL x, y, r, c; } p[N]; vector<int> edge[N]; void tarjan(int u) { st[top++] = u; ++idx; low[u] = dfn[u] = idx; in[u] = true; for(int v : edge[u]) { if(!dfn[v]) { tarjan(v); low[u] = min(low[u], low[v]); } else if(in[v]) { low[u] = min(low[u], dfn[v]); } } if(low[u] == dfn[u]) { cnt++; while(1) { int now = st[--top]; in[now] = false; id[now] = cnt; cost[cnt] = min(cost[cnt], p[now].c); if(now == u) break; } } } void init() { idx = 0; top = 0; cnt = 0; memset(deg, 0, sizeof(deg)); memset(cost, inf, sizeof(cost)); memset(dfn, 0, sizeof(dfn)); memset(in, 0, sizeof(in)); for(int i = 1; i <= n; i++) edge[i].clear(); } LL dis(LL a, LL b, LL c, LL d) { return ((a - c) * (a - c) + (b - d) * (b - d)); } int main() { int T; scanf("%d", &T); for(int cas = 1; cas <= T; cas++) { init(); scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%lld%lld%lld%lld", &p[i].x, &p[i].y, &p[i].r, &p[i].c); for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { if(i == j) continue; if(dis(p[i].x, p[i].y, p[j].x, p[j].y) <= p[i].r * p[i].r) { edge[i].push_back(j); } } } for(int i = 1; i <= n; i++) { if(!dfn[i]) tarjan(i); } for(int u = 1; u <= n; u++) { for(int v : edge[u]) { if(id[u] != id[v]) { deg[id[v]]++; } } } LL ans = 0; for(int i = 1; i <= cnt; i++) if(deg[i] == 0) ans += cost[i]; printf("Case #%d: ", cas); printf("%lld\n", ans); } return 0; } /* */
C:题意:有一辆车,n个记录点,要求车速度只能增加,每次通过记录点的时间为整数,问通过n个记录点的最小时间
题解:把加速看成一瞬间,其他都是匀速,那么有vi=si/ti<=si+1/ti+1,可得ti>=si*ti+1/si+1,从后往前贪心即可
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
//#pragma comment(linker, "/stack:200000000") //#pragma GCC optimize("Ofast,no-stack-protector") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") //#pragma GCC optimize("unroll-loops") #include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pi acos(-1.0) #define ll long long #define vi vector<int> #define mod 10007 #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pli pair<ll,int> #define pii pair<int,int> #define cd complex<double> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double eps=1e-6; const int N=100000+10,maxn=5000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; ll a[N],b[N]; int main() { int T;scanf("%d",&T); for(int _=1;_<=T;_++) { int n;scanf("%d",&n); a[0]=0; for(int i=1;i<=n;i++)scanf("%lld",&a[i]); for(int i=0;i<n;i++)b[i]=a[i+1]-a[i]; ll ans=1,last=1; for(int i=n-2;i>=0;i--) { int now=b[i]*last/b[i+1]; if(b[i]*last%b[i+1]!=0)now++; last=now; ans+=last; } printf("Case #%d: %lld\n",_,ans); } return 0; } /******************** ********************/
D:题意:f(y,k)代表y的每一位的k次方之和,给你x,k求满足x=f(y,k)-y的对数
题解:折半枚举,把前5位预处理出来,然后枚举后5位算答案
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
//#pragma comment(linker, "/stack:200000000") //#pragma GCC optimize("Ofast,no-stack-protector") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") //#pragma GCC optimize("unroll-loops") #include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pi acos(-1.0) #define ll long long #define vi vector<int> #define mod 1000000007 #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pli pair<ll,int> #define pii pair<int,int> #define cd complex<double> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double g=10.0,eps=1e-12; const int N=10+10,maxn=1000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; int x,kk; int f[11][11]; map<ll,int>m[10]; void prepare() { for(int i=1;i<=9;i++) { f[i][0]=1; for(int j=1;j<=10;j++)f[i][j]=f[i][j-1]*i; } for(int kk=1;kk<=9;kk++) { for(int i=0;i<=99999;i++) { ll te=0,ii=i,now=100000; for(int j=5;j<=9;j++) { te+=f[ii%10][kk]-(ii%10)*now; ii/=10;now*=10ll; } m[kk][te]++; } } } void solve() { ll ans=0; for(int i=0;i<=99999;i++) { ll te=0,ii=i,now=1; for(int j=0;j<=4;j++) { te+=f[ii%10][kk]-(ii%10)*now; ii/=10;now*=10ll; } if(m[kk].find(x-te)!=m[kk].end())ans+=m[kk][x-te]; } printf("%lld\n",ans-(x==0)); } int main() { prepare(); int T;scanf("%d",&T); for(int _=1;_<=T;_++) { scanf("%d%d",&x,&kk); printf("Case #%d: ",_); solve(); } return 0; } /*********************** ***********************/
E:题意:给1到9的每个数字出现次数,你每次选3个数构成x+y=z的等式,问不同的等式最多有多少个
题解:爆搜+剪枝,枚举20种方程,x+y=z,y+x=z算一种,加的时候分开算即可,剪枝:当前方程数+剩余数字数/3<最大答案,剩余方程数+当前方程<最大答案,
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
//#pragma comment(linker, "/stack:200000000") //#pragma GCC optimize("Ofast,no-stack-protector") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") //#pragma GCC optimize("unroll-loops") #include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pi acos(-1.0) #define ll long long #define vi vector<int> #define mod 1000000007 #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pli pair<ll,int> #define pii pair<int,int> #define cd complex<double> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double eps=1e-6; const int N=1000000+10,maxn=5000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; int eq[20][3]={ {1,1,2}, {1,2,3}, {1,3,4}, {1,4,5}, {1,5,6}, {1,6,7}, {1,7,8}, {1,8,9}, {2,2,4}, {2,3,5}, {2,4,6}, {2,5,7}, {2,6,8}, {2,7,9}, {3,3,6}, {3,4,7}, {3,5,8}, {3,6,9}, {4,4,8}, {4,5,9} }; int a[10],res[20]; void dfs(int a[],int id,int now,int &ans) { int sum=0; for(int i=1;i<=9;i++) { if(a[i]<0)return ; else sum+=a[i]; } if(sum/3+now<ans)return ; if(res[id]+now<ans)return ; if(id==20) { ans=max(ans,now); return ; } dfs(a,id+1,now,ans); if(a[eq[id][0]]>=1&&a[eq[id][1]]>=1&&a[eq[id][2]]>=1) { a[eq[id][0]]--;a[eq[id][1]]--;a[eq[id][2]]--; dfs(a,id+1,now+1,ans); a[eq[id][0]]++;a[eq[id][1]]++;a[eq[id][2]]++; } if(eq[id][0]!=eq[id][1]&&a[eq[id][0]]>=2&&a[eq[id][1]]>=2&&a[eq[id][2]]>=2) { a[eq[id][0]]-=2;a[eq[id][1]]-=2;a[eq[id][2]]-=2; dfs(a,id+1,now+2,ans); a[eq[id][0]]+=2;a[eq[id][1]]+=2;a[eq[id][2]]+=2; } } int main() { for(int i=19;i>=0;i--) { if(eq[i][0]==eq[i][1])res[i]=res[i+1]+1; else res[i]=res[i+1]+2; } int T;scanf("%d",&T); for(int _=1;_<=T;_++) { for(int i=1;i<=9;i++)scanf("%d",&a[i]); int ans=0; dfs(a,0,0,ans); printf("Case #%d: %d\n",_,ans); } return 0; } /******************** ********************/
F:题意:给一个1到9组成的字符串,按顺序插入+-*/,求最大的数
题解:由于*/优先级高,而且又是被减的,故越小越好,*/插在最后两位即可,注意有6位时,可能有问题,比如,111991,特判掉就好了,前面的+也是,选一个一位数,和剩余的加看哪个大就选哪个
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
//#pragma comment(linker, "/stack:200000000") //#pragma GCC optimize("Ofast,no-stack-protector") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") //#pragma GCC optimize("unroll-loops") #include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pi acos(-1.0) #define ll long long #define vi vector<int> #define mod 12345678 #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pli pair<ll,int> #define pii pair<int,int> #define cd complex<double> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double eps=1e-6; const int N=300+10,maxn=5000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; char s[N]; ll cal(int a,int b) { ll ans=0; for(int i=a;i<=b;i++) ans=ans*10+(s[i]-'0'); return ans; } int main() { int T;scanf("%d",&T); for(int _=1;_<=T;_++) { printf("Case #%d: ",_); scanf("%s",s); int n=strlen(s); ll ans1=cal(0,0)+cal(1,n-4)-cal(n-3,n-3)*cal(n-2,n-2)/cal(n-1,n-1); ll ans2=cal(0,n-5)+cal(n-4,n-4)-cal(n-3,n-3)*cal(n-2,n-2)/cal(n-1,n-1); if(n==6){ long long ans=-1e18; for(int i=0;i<n-1;i++) for(int j=i+1;j<n-1;j++) for(int k=j+1;k<n-1;k++) for(int u=k+1;u<n-1;u++){ //printf("%d %d %d %d\n",i,j,k,u); ans1=max(ans1,cal(0,i)+cal(i+1,j)-cal(j+1,k)*cal(k+1,u)/cal(u+1,n-1)); } } printf("%lld\n",max(ans1,ans2)); } return 0; }
j:题意:求1到n的每一个数的2的质因子和,
题解:对于每个数x来说可以化成p1^c1*...*pk^ck,对于2^k来说就等价于∑(d|x)|μ(d)|,根据莫比乌斯函数的性质,μ(d)=(-1)^k,d=p1*p2...pk,相当于每次只选k个质因子,然后因为可能为负数,所以变成∑(d|x)μ(d)^2
∑(1<=i<=n)∑(d|i)μ(d)^2,假设j^2是d的最大平方因子,那么∑(k|j)μ(k)=∑(k^2|j^2)μ(k)=∑(k^2|d)μ(k),所以∑(1<=i<=n)∑(d|i)∑(k^2|d)μ(d)=∑(1<=i<=n)μ(k)∑(k^2|d)[n/(k^2)],因为k>sqrt(n)时后面变成了0,所以只需要算前sqrt(n)即可,记忆化后面,μ预处理出来
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
//#pragma comment(linker, "/stack:200000000") //#pragma GCC optimize("Ofast,no-stack-protector") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") //#pragma GCC optimize("unroll-loops") #include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pi acos(-1.0) #define ll long long #define vi vector<int> #define mod 1000000007 #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pli pair<ll,int> #define pii pair<int,int> #define cd complex<double> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double eps=1e-6; const int N=1000000+10,maxn=5000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; ll n,f[N]; int prime[N],mu[N]; bool notprime[N]; void init() { int cnt=0;mu[1]=1; for(int i=2;i<N;i++) { if(!notprime[i])prime[++cnt]=i,mu[i]=-1; for(int j=1;j<=cnt&&i*prime[j]<N;j++) { notprime[i*prime[j]]=1; mu[i*prime[j]]=-mu[i]; if(i%prime[j]==0){mu[i*prime[j]]=0;break;} } } } ll cal(ll n) { if(n<N&&f[n])return f[n]; ll ans=0; for(ll i=1,j;i<=n;i=j+1) { j=n/(n/i); ans+=n/i*(j-i+1)%mod; ans%=mod; } if(n<N)f[n]=ans; return ans; } int main() { init(); int T;scanf("%d",&T); for(int _=1;_<=T;_++) { scanf("%lld",&n); printf("Case #%d: ",_); ll ans=0; for(ll i=1;i<=n/i;i++) { if(mu[i]==0)continue; ans+=mu[i]*cal(n/i/i)%mod; ans=(ans%mod+mod)%mod; } printf("%lld\n",ans); } return 0; } /******************** ********************/
K:题意:给你s,n,问你s+1....s+n能不能每个对应一个因子是1到n,而且1到n每个只出现一次
题解:因为如果s+1到s+n和1到n有重叠,那么就选自己,然后剩余的数每个数和因子连边,二分图匹配即可,(也是队友写的)
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int,int> #define piii pair<int,pair<int,int>> using namespace std; const int N = 500 + 7; const int M = 1e4 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; int T, n, s, match[N]; bool edge[N][N], vis[N]; bool path(int u) { for(int v = 1; v <= n; v++) { if(edge[u][v] && !vis[v]) { vis[v] = true; if(!match[v] || path(match[v])) { match[v] = u; return true; } } } return false; } int main() { scanf("%d", &T); for(int cas = 1; cas <= T; cas++) { memset(match, 0, sizeof(match)); memset(edge, 0, sizeof(edge)); scanf("%d%d", &n, &s); if(s == 0 || s == 1) { printf("Case #%d: ", cas); puts("Yes"); continue; } int l1 = 1, r1 = n; int l2 = s + 1, r2 = s + n; if(r1 >= l2) { swap(l2, r1); l2++; r1--; } n = r2 - l2 + 1; if(n > 500) { printf("Case #%d: ", cas); puts("No"); } else { for(int i = l2; i <= r2; i++) { for(int j = l1; j <= r1; j++) { if(i % j == 0) { edge[i - l2 + 1][j - l1 + 1] = true; } } } bool flag = true; for(int i = 1; i <= n; i++) { memset(vis, 0, sizeof(vis)); if(!path(i)) { flag = false; break; } } printf("Case #%d: ", cas); if(flag) puts("Yes"); else puts("No"); } } return 0; } /* */