A:签到。
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 char getc(){char c=getchar();while ((c<‘A‘||c>‘Z‘)&&(c<‘a‘||c>‘z‘)&&(c<‘0‘||c>‘9‘)) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();} while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,m; signed main() { n=read(),m=read(); if (m==1) cout<<0;else cout<<n-m; return 0; //NOTICE LONG LONG!!!!! }
B:若将所有差是(p,q)的点对连接起来,显然会得到若干条链,链的数量即为答案。于是只要统计每种差的出现次数即可。
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 #define N 55 char getc(){char c=getchar();while ((c<‘A‘||c>‘Z‘)&&(c<‘a‘||c>‘z‘)&&(c<‘0‘||c>‘9‘)) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();} while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } typedef pair<int,int> pii; int n,ans; struct data{int x,y; }a[N]; map<pii,int> f; signed main() { n=read(); for (int i=1;i<=n;i++) a[i].x=read(),a[i].y=read(); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if (i!=j) { ans=max(ans,++f[make_pair(a[i].x-a[j].x,a[i].y-a[j].y)]); } cout<<n-ans; return 0; //NOTICE LONG LONG!!!!! }
C:显然应该尽量加正数减负数。但同时容易发现至少有一个数要被减掉,至少有一个数要被加上,所以均为正数或均为负数时稍微修改一下。不妨设是排序后要将前p个数减掉,其他数加上。那么令a1依次减去ap+1~an-1,再令an依次减去a1~ap即可。
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 #define N 100010 char getc(){char c=getchar();while ((c<‘A‘||c>‘Z‘)&&(c<‘a‘||c>‘z‘)&&(c<‘0‘||c>‘9‘)) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();} while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,a[N]; signed main() { n=read(); for (int i=1;i<=n;i++) a[i]=read(); sort(a+1,a+n+1); int p=0; for (int i=1;i<=n;i++) if (a[i]<0) p=i; p=max(p,1);p=min(p,n-1); //让前p个被减掉 int s=0; for (int i=1;i<=p;i++) s-=a[i]; for (int i=p+1;i<=n;i++) s+=a[i]; cout<<s<<endl; for (int i=p+1;i<n;i++) { printf("%d %d\n",a[p],a[i]); a[p]-=a[i]; } printf("%d %d\n",a[n],a[p]);a[n]-=a[p]; for (int i=1;i<p;i++) { printf("%d %d\n",a[n],a[i]); a[n]-=a[i]; } return 0; //NOTICE LONG LONG!!!!! }
D:显然A到B和B到A的过程是独立的,分别最优化即可。显然就是做一个完全背包。需要注意的是第二次完全背包值域是5000*5000,且答案会爆int。
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 #define N (5010*5010) char getc(){char c=getchar();while ((c<‘A‘||c>‘Z‘)&&(c<‘a‘||c>‘z‘)&&(c<‘0‘||c>‘9‘)) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();} while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,a[2][3]; ll f[N]; ll solve(int x,int y,int n) { for (int i=0;i<=n;i++) f[i]=i; for (int i=0;i<3;i++) for (int j=a[x][i];j<=n;j++) f[j]=max(f[j],f[j-a[x][i]]+a[y][i]); return f[n]; }//有n元钱 从x买入 y卖出 最后最多能剩多少 signed main() { n=read(); for (int i=0;i<2;i++) for (int j=0;j<3;j++) a[i][j]=read(); cout<<solve(1,0,solve(0,1,n)); return 0; //NOTICE LONG LONG!!!!! }
E:设f[i][j]为最大数是i且有j个时的方案数,尴尬的是转移需要用到最小值数量,并且无法记录。但注意到从最小值中挑一个和把一个数变成最大值之一的过程是一一对应的,所以在新增最大值时直接将贡献乘进去即可。那么上面的dp容易得到f[i][j]=f[i][j-1]*j,于是只要记录f[i][1]并转移。
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 #define N 1000010 #define P 1000000007 char getc(){char c=getchar();while ((c<‘A‘||c>‘Z‘)&&(c<‘a‘||c>‘z‘)&&(c<‘0‘||c>‘9‘)) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();} while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,h,d,f[N],sum[N],s,t; int ksm(int a,int k) { int s=1; for (;k;k>>=1,a=1ll*a*a%P) if (k&1) s=1ll*s*a%P; return s; } int inv(int a){return ksm(a,P-2);} signed main() { n=read(),h=read(),d=read(); s=t=1; for (int i=2;i<=n;i++) { t=1ll*t*i%P; s=(s+t)%P; } f[0]=inv(s);sum[0]=f[0]; for (int i=1;i<=h;i++) { int u=(sum[i-1]-(i>d?sum[i-d-1]:0)+P)%P; f[i]=1ll*u*s%P; sum[i]=(sum[i-1]+f[i])%P; } for (int i=n;i>=1;i--) f[h]=1ll*f[h]*i%P; cout<<f[h]; return 0; //NOTICE LONG LONG!!!!! }
result:rank 98 rating +38
原文地址:https://www.cnblogs.com/Gloid/p/11031179.html
时间: 2024-10-07 02:37:11