比赛链接:https://ac.nowcoder.com/acm/contest/15703#question
那些输出“输出Welcome to The First Programming Competition of Hebei University of technology!”的把我人秀麻了,好想笑(磕头了o…orz)
#include
using namespace std;
int main()
{
cout<<"Welcome to The First Programming Competition of Hebei University of technology!"<<endl;
return 0;
}
当时想着把i~i+k-1行j列的最大值存到i行j列之后输出i行j列的数只需要比较i行j ~ j+k-1列的最大值即可
PS:反正咋都不会错随便搞。
#include
using namespace std;
#define ll long long
#define pii pair
#define mod 1000000007
int a[57][57];
int b[57][57];
int main()
{
int n,m,k;
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
if(i>=k)
{
for(int l=i-k+1;l<=i;l++)
{
b[i-k+1][j]=max(b[i-k+1][j],a[l][j]);
}
}
}
for(int i=1;i<=n-k+1;i++)
{
for(int j=1;j<=m-k+1;j++)
{
for(int l=j+1;l<=j+k-1;l++)
{
b[i][j]=max(b[i][j],b[i][l]);
}
}
}
printf("%d %d\n",n-k+1,m-k+1);
for(int i=1;i<=n-k+1;i++)
{
printf("%d",b[i][1]);
for(int j=2;j<=m-k+1;j++)
{
printf(" %d",b[i][j]);
}
printf("\n");
}
return 0;
}
出题人给的题解是离散化加树状数组,因为当时想离散化时有(没)点(get到)怕(好)冲(方)突(法),果断say no!
活用STL嘛,vector挺好用的(cf选手特别热衷?)upper_bound二分找到第一个大于numi的数的下标,也就是标枪的正得分(还有本身的标枪别忘记+1哦),负得分即为vector的元素个数减去下标。不用担心二分是不是顺序的问题,每一次插入都是按顺序插入(vector有内置插入函数嘛,下标都找到了还怕插不进去吗)
#include
using namespace std;
#define ll long long
#define pii pair
const ll mod=1e9+7;
vector<ll>v1;
int main()
{
ll n;
cin>>n;
ll ans1=0,ans2=0;
for(ll i=1;i<=n;i++)
{
ll p;
scanf("%lld",&p);
if(i%2)
{
auto it=upper_bound(v1.begin(),v1.end(),p);
ans1+=it-v1.begin()+1;
ans1-=v1.size()-(it-v1.begin());
v1.insert(it,p);
}
else{
auto it=upper_bound(v1.begin(),v1.end(),p);
ans2+=it-v1.begin()+1;
ans2-=v1.size()-(it-v1.begin());
v1.insert(it,p);
}
}
if(ans1>ans2)
{
cout<<"Calculus is hebei king!"<<endl;
}
if(ans1==ans2)
{
cout<<"hebei shuang king!"<<endl;
}
if(ans1<ans2)
{
cout<<"huaji is hebei king!"<<endl;
}
return 0;
}
因为是按顺序走的所以我们只需要求出第i个景点到第i+1个景点的最短路程方案数,再求乘积就是答案。
最短路程方案数怎么求呢,我们发现不管两个点怎么给坐标(a1,b1),(a2,b2),我们都可以简化为一个从点(0,0)到(abs(a1-a2),abs(b1-b2))的问题,这样可能一小部分长的比较帅的观众已经看出来了,这就是一个简单模型:从(0,0)到(n,m)只能向下和向右左的方案数,即C(n+m,n);
套个组合数板子直接A了
#include
using namespace std;
#define ll long long
#define pii pair
const ll mod=1e9+7;
struct node
{
int x,y;
}a[100007];
ll fac[2000007];
ll ksm(ll x,ll p){
ll res=1;
while(p){
if(p%2==1) res=res*x%mod;
p/=2;
x=x*x%mod;
}
return res;
}
ll inv(ll a) {
return ksm(a,mod-2)%mod;
}
void solve() {
fac[0] = 1;
for(int i = 1;i < 2000006; i++) {
fac[i] = (fac[i-1]*i)%mod;
}
}
ll comb(ll n,ll k){
if(k>n)return 0;
if(k==1)return n;
return (fac[n]*inv(fac[k])%mod*inv(fac[n-k])%mod);
}
int main()
{
solve();
int n,m,k;
cin>>n>>m>>k;
int num=0;
a[++num].x=1;
a[num].y=1;
for(int i=1;i<=k;i++)
{
int x,y;
scanf("%d%d",&x,&y);
a[++num].x=x;
a[num].y=y;
}
a[++num].x=n;
a[num].y=m;
ll ans=1;
for(int i=1;i<=num-1;i++)
{
int xx=min(a[i].x,a[i+1].x),yy=min(a[i].y,a[i+1].y);
int xx1=max(a[i].x,a[i+1].x),yy1=max(a[i].y,a[i+1].y);
ll pp=comb(xx1-xx+yy1-yy,xx1-xx);
ans=ans*pp%mod;
}
cout<<ans<<endl;
return 0;
}
出题人已经解释的很清晰了,再就是输出ai一定不要递归%k就输出,会少输出喜提0分,别问我怎么知道的。。。
#include
using namespace std;
#define ll long long
#define pii pair
const ll mod=1e18;
ll k,m,p;
ll ksm(ll a,ll b)
{
ll r=1,base=a;
while(b!=0)
{
if(b%2)
r=r*base%mod;
base=base*base%mod;
b/=2;
}
return r%mod;
}
void print(ll x,ll num)
{
if(!num) return;
print(x/k,num-1);
cout<<x%k<<' ';
}
int main()
{
ll t;
cin>>t;
while(t--)
{
cin>>k>>m>>p;
ll ans=ksm(k,m)-1;
cout<<ans<<endl;
if(ans<p)
{
cout<<"overflow"<<endl;
}
else
{
p=ans+1-p;
print(p,m);
cout<<endl;
}
}
return 0;
}
最少一组,最多字符串多长就多少组。字母数量为奇数即需要新开一组才能回文。
#include
using namespace std;
#define ll long long
#define pii pair
#define mod 1000000007
int a[107];
int main()
{
string s;
cin>>s;
int si=s.size();
for(int i=0;i<si;i++)
{
a[s[i]-'a'+1]++;
}
int num=0,ans=0;
for(int i=1;i<=26;i++)
{
if(a[i]%2==1)
num++;
ans+=a[i]/2;
}
printf("%d\n",max(num,1));
return 0;
}
是的好难啊,非数据结构选手我不会。先空着
大模拟,狗都不做!
PS:计算几何,狗都不做!还卡我精度!
#include
using namespace std;
#define ll long long
#define pii pair
const ll mod=1e9+7;
const double eps=0.000001;
const double PI=acos(-1.0);
struct point
{
double x,y;
point(){
}
point(double xx,double yy){
x=xx,y=yy;
}
};
struct line {
point a, b;
line(point aa,point bb){
a=aa,b=bb;
}
};
class circle {
//circle 圆
public:
point c;
double r;
circle(point c = point(), double r = 0.0): c(c), r(r) {
}
};
point operator - (point A,point B){
return point(A.x-B.x, A.y-B.y);
}
point operator + (point A, point B){
return point(A.x+B.x, A.y+B.y);
}
point operator * (point A, double p){
return point(A.x*p, A.y*p);
}
bool operator == (point A, point B){
return (A.x-B.x) == 0 && (A.y-B.y) == 0;
}
int sgn(double x)
{
if (fabs(x) < eps)return 0;
else return x < 0 ? -1 : 1;
}
double cross(point p1,point p2,point p3){
//叉积
return (p2.x-p1.x)*(p3.y-p1.y)-(p2.y-p1.y)*(p3.x-p1.x);
}
double dot(point p1,point p2,point p3){
//点积
return (p2.x-p1.x)*(p3.x-p1.x)+(p2.y-p1.y)*(p3.y-p1.y);
}
double dis(point A, point B){
//长度
return sqrt((A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y));
}
//点到直线的距离
double Dis_point_line(point p, line v)
{
return fabs(cross(v.a,p , v.b )) / dis(v.a, v.b);
}
double disOfPointToLine(point p,line v){
if (sgn(dot(v.a,p,v.b)) < 0||sgn(dot(v.b,p,v.a)) < 0)
return min(dis(p, v.a), dis(p, v.b));
return Dis_point_line(p, v);
}
point GetLineIntersection(line u,line v) {
//两直线交点
point ret = u.a;
double t = ((u.a.x-v.a.x) * (v.a.y-v.b.y) - (u.a.y-v.a.y) * (v.a.x-v.b.x)) / ((u.a.x-u.b.x) * (v.a.y-v.b.y) - (u.a.y-u.b.y) * (v.a.x-v.b.x));
ret.x += (u.b.x - u.a.x) * t;
ret.y += (u.b.y - u.a.y) * t;
return ret;
}
//两向量OA,OB夹角
double angle(point O,point A,point B){
return acos(dot(O,A,B)/(dis(O,A)*dis(O,B)));
}
//扇形面积alpha*pi*r*r/2*pi
double sectorArea(point O,point A,point B,double r){
double alpha=angle(O,A,B);
return alpha*r*r/2;
}
int Seg_circle_relation(line v, circle C)//线段和圆的关系
{
double dst = disOfPointToLine(C.c, v);
if (sgn(dst - C.r) < 0)return 0;
if (sgn(dst - C.r) == 0)return 1;//相切
return 2;//圆外
}
int main()
{
circle O;
point A,B;
scanf("%lf%lf%lf%lf%lf%lf%lf", &O.c.x, &O.c.y, &O.r, &A.x, &A.y, &B.x, &B.y);
double area=PI*O.r*O.r;
line v(A,B);
if (Seg_circle_relation(v, O) == 1 || Seg_circle_relation(v, O) == 2)//不与圆相交
{
double sanArea = fabs(cross(O.c, A, B) / 2);
double jiao = angle(O.c, A, B);
double aa = area * (jiao / (2 * PI));
double ans = area + sanArea - aa;
printf("%.4lf\n", ans);
}
else//与圆相交
{
double lenOB = dis(O.c, B);
double lenOA = dis(O.c, A);
double lenA = sqrt(lenOA * lenOA - O.r * O.r);
double lenB = sqrt(lenOB * lenOB - O.r * O.r);
double AreaOA = lenA * O.r / 2.0;
double AreaOB = lenB * O.r / 2.0;
double ans = area + AreaOA + AreaOB;
double ss1 = (lenOA * lenOA + O.r * O.r - lenA * lenA) / (2 * lenOA * O.r);
double ss2 = (lenOB * lenOB + O.r * O.r - lenB * lenB) / (2 * lenOB * O.r);
double jiaoA = acos(ss1);
double jiaoB = acos(ss2);
ans -= (jiaoA + jiaoB) / (2 * PI) * area;
printf("%.4lf\n", ans);
}
return 0;
}
第一眼,什么东西???第二眼,我还是先看看上面写的什么吧。一分钟后,算了看一下要求什么。第三眼,写那么多干甚莫啦,神经病呀!
只有a1到am全部相等时才满足条件。
也就是说直接1加到n,与k毫无关系,本来还用了个逆元和慢速乘,刚刚试了一下,直接乘也能过。giao!
#include
using namespace std;
#define ll long long
#define pii pair
const ll mod=1e9+7;
const int maxn=1e6+5;
int main()
{
int n,k;
cin>>n>>k;
ll ans=(n*(n+1))%mod/2;
cout<<ans<<endl;
return 0;
}
搞了挺久的,基本不用dijstra选手,突然写多源汇最短路头都麻了,一直试图dfs优化看能不能过,无奈倒在了81.82分再上不去,没办法dijstra吧。
只要在0节点接上所有起点,n+1节点接上所有终点,再去跑dijstra就OK啦!维护一个到达该节点最短路径时最少礼物数数组cnt。
PS:一直都是队友写的图论,好久没写dijstra居然都不会写了,批评一下自己!
借鉴了一下madoka大佬的代码
#include
using namespace std;
#define ll long long
#define pii pair
const ll mod=1e9+7;
const double eps=0.000001;
const double PI=acos(-1.0);
#define mk make_pair
struct node{
ll p,c,k;
bool operator<(const node &now)const{
return c>now.c;
}
};
ll n,m,n1,n2,k;
vector<pii>v[100007];
ll dist[100010],vis[100010],cnt[100010];
void bfs()
{
priority_queue<node>q;
q.push({
0,0,0});
while(!q.empty())
{
ll p=q.top().p;
ll c=q.top().c;
ll k=q.top().k;
q.pop();
if(vis[p]) continue;
vis[p]=1;
if(c<dist[p])
{
dist[p]=c;
cnt[p]=k;
}
else if(c==dist[p]&&cnt[p]>k)
{
cnt[p]=k;
}
else{
continue;
}
for(int i=0;i<v[p].size();i++)
{
ll to=v[p][i].first;
ll co=v[p][i].second;
cnt[to]=min(co+c,cnt[to]);
q.push({
to,co+c,k+1});
}
}
}
int main()
{
cin>>n>>m>>n1>>n2>>k;
memset(dist,0x3f,sizeof(dist));
memset(cnt,0x3f,sizeof(cnt));
for(int i=1;i<=n1;i++)
{
ll q;
scanf("%lld",&q);
v[0].push_back(mk(q,0));
}
for(int i=1;i<=n2;i++)
{
ll b;
scanf("%lld",&b);
v[b].push_back(mk(n+1,0));
}
for(int i=1;i<=m;i++)
{
ll a,b,c;
scanf("%lld%lld%lld",&a,&b,&c);
v[a].push_back(mk(b,c));
}
bfs();
if(cnt[n+1]>k)
{
printf("we break up\n");
}
else{
printf("%lld\n",k-cnt[n+1]+1);
}
return 0;
}
网络流不会鸭