洛谷 11 月月賽 II div.2 T2&T3 題解
阿新 • • 發佈:2020-11-29
T2
P7107 天選之人
https://www.luogu.com.cn/problem/P7107?contestId=13515
根據貪心,那p個人最多各能拿到p/k個有記號的紙團
如果p/k>m不就爆0了???!!!
所以要判一下
於是得到了判斷YES/NO的語句(能用乘法絕對不用除法,不然就可以開心地爆0了)(av是平均的意思...)
(n - p) * (av - 1) >= k - av * p
然後就是YES的輸出啦
p個人抽到了av張,然下的人能儘量拿av-1張,如果剩餘的不夠了,拿掉剩下的,其餘的人拿0張
#include<bits/stdc++.h> #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) #define int long long #define re register #define mod 998244353 #define inf 0x3f3f3f3f using namespace std; const int N=300005; int n,m,k,d,t,sum,mi,p; char a[N]; int b[N]; template <class T> inline void read(T &x){ x=0;int g=1; char s=getchar(); for (;s>'9'||s<'0';s=getchar()) if (s=='-') g=-1; for (;s<='9'&&s>='0';s=getchar()) x=(x<<1)+(x<<3)+(s^48); x*=g; } signed main() { re int i,j,x,y,z; read(n);read(m);read(k);read(p); if(n==p&&k%p!=0) return printf("NO"),0; int av=k/p; if (av>m) av=m; int tmp=k-av*p,cnt=0; if ((n - p) * (av - 1) >= k - av * p)//av>ceil(tmp*1.0/(n-p) ??????//////(n - p) * (av - 1) >= k - av * p { printf("YES\n"); for (i=1;i<=p;i++) printf("%lld %lld\n",av,m-av); while(tmp) { if (tmp>=av-1) printf("%lld %lld\n",av-1,m-av+1),tmp-=av-1; else printf("%lld %lld\n",tmp,m-tmp),tmp=0; cnt++; } for (i=1;i<=n-p-cnt;i++) printf("%lld %lld\n",0,m); } else printf("NO"); return 0; }
T3
P7108 移花接木
https://www.luogu.com.cn/problem/P7107?contestId=13515
對a,b的大小進行討論
當a<=b時,因為要刪掉的操作一定多餘接上的操作,所以可以把一些刪掉的接上去算作一步,所以答案是a*(b的h次方)
當a>b時,不僅h+1層的節點都要刪,第0層有b的0次方個節點,共有1(a-b)個要刪除的兒子,第1層有b的1次方個節點,共有b(a-b)個要刪除的兒子...第h-1層有b的h-1次方個節點,共有(b的h-1次方)*(a-b)個要刪除的兒子
然後用等比數列求和逆元做
注意:公比是1的數列不能用公式,否則100pts-->30pts
#include<bits/stdc++.h> #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) #define int long long #define re register #define mod 1000000007 #define inf 0x3f3f3f3f using namespace std; const int N=300005; int n,m,k,d,t,p,h,a,b; int poww(int x,int y) { int tmp=1; for (;y;x=x*x%mod,y>>=1) if (y&1) tmp=tmp*x%mod; return tmp; } int ny(int x) { return poww(x,mod-2); } template <class T> inline void read(T &x){ x=0;int g=1; char s=getchar(); for (;s>'9'||s<'0';s=getchar()) if (s=='-') g=-1; for (;s<='9'&&s>='0';s=getchar()) x=(x<<1)+(x<<3)+(s^48); x*=g; } signed main() { re int i,j,x,y,z; read(t); while(t--) { read(a);read(b);read(h); int tmp=poww(b,h); if (a>b) { if(b==1) printf("%lld\n",((a-b)*h%mod+a*tmp%mod)%mod); else printf("%lld\n",((a-b)*(tmp-1)%mod*ny(b-1)%mod+a*tmp%mod)%mod); } else printf("%lld\n",a*tmp%mod); } return 0; }