10.15测试
T1 pay
Sol
扩欧求最小解,然后计算方案数和总和。注意一细节即可。不过我根本没写扩欧,我求最小解用的暴力...但是可以证明暴力的时间复杂度不超过\(O(\sqrt n)\)。
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=0;c=getchar();}
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c&15),c=getchar();
return f?x:-x;
}
inline int gcd(int x,int y)
{
while(y){int t=y;y=x%y;x=t;}
return x;
}
int T,opt,a,b,c,ans1,ans2;
inline void getans()
{
ans1=ans2=0;
int g=gcd(a,b);
if(c%g!=0)return;
a/=g;b/=g;c/=g;
if(a>b)swap(a,b);
if(c<b)
{
if(c%a==0)ans1=1,ans2=c/a;
return;
}
if(c<=a*b)
{
for(int i=0;i<=c/b;i++)
{
if((c-b*i)%a==0)
{
ans1=1;ans2=i+(c-b*i)/a;
return;
}
}
return;
}
int ti=c/(a*b)-1;
c=c%(a*b)+a*b;
for(int i=0;i<=c/b;i++)
{
if((c-b*i)%a==0)
{
if(c-b*i>=a*b)
{
ans1=ti+2;
int fi=i+(c-b*i-a*b)/a+(ti+1)*a;
int la=i+(c-b*i-a*b)/a+(ti+1)*b;
ans2=(fi+la)*ans1/2;
return;
}else
{
ans1=ti+1;
int fi=i+(c-b*i)/a+ti*a;
int la=i+(c-b*i)/a+ti*b;
ans2=(fi+la)*ans1/2;
return;
}
}
}
return;
}
signed main()
{
freopen("pay.in","r",stdin);
freopen("pay.out","w",stdout);
T=read();opt=read();
while(T--)
{
a=read();b=read();c=read();
getans();
if(opt==1)printf("%lld\n",ans1);
else printf("%lld %lld\n",ans1,ans2);
}
}
T2 sumcomb
Sol
把求的两种答案拆解一下容易发现就是平移后的杨辉三角。证明如下:讲定义中的一列求解,把每一项在杨辉三角中拆开,就变成了两列,所以依然符合杨辉三角的性质,初始值特殊处理即可。对于斜着的讲杨辉三角翻转后与竖直的情况一样。
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=0;c=getchar();}
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c&15),c=getchar();
return f?x:-x;
}
const int p=1000000007,maxn=1000010;
int T,n,m,opt;
int fac[maxn],facinv[maxn];
inline int ksm(int x,int mi)
{
int ans=1;
while(mi)
{
if(mi&1)ans=ans*x%p;
x=x*x%p;mi>>=1;
}
return ans;
}
inline void pre(int mx)
{
fac[0]=facinv[0]=1;
for(int i=1;i<=mx;i++)fac[i]=fac[i-1]*i%p;
facinv[mx]=ksm(fac[mx],p-2);
for(int i=mx-1;i;i--)facinv[i]=facinv[i+1]*(i+1)%p;
return;
}
inline int C(int x,int y)
{
// cout<<fac[x]<<" "<<facinv[y]<<" "<<facinv[x-y]<<endl;
return fac[x]*facinv[y]%p*facinv[x-y]%p;
}
signed main()
{
freopen("sumcomb.in","r",stdin);
freopen("sumcomb.out","w",stdout);
T=read();pre(1000000);
while(T--)
{
int opt=read(),n=read(),m=read();
if(n<m)
{
printf("0\n");
continue;
}
if(opt==2)m=n-m;
printf("%lld\n",C(n+1,m+1));
}
return 0;
}
//C(n+1,m+1)
T3 kor
Sol
容斥原理+反演,搞不懂。
Code(贺的)
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int p=1000000007,maxn=100010,P=20;
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=0;c=getchar();}
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c&15),c=getchar();
return f?x:-x;
}
int T,n,k,r;
int a[maxn],t[(1<<20)+10];
int fac[maxn],facinv[maxn],pw[maxn];
inline int ksm(int x,int mi)
{
int ans=1;
while(mi)
{
if(mi&1)ans=ans*x%p;
x=x*x%p;mi>>=1;
}
return ans;
}
inline void pre(int mx)
{
fac[0]=facinv[0]=pw[0]=1;
for(int i=1;i<=P;i++)pw[i]=pw[i-1]<<1;
for(int i=1;i<=mx;i++)fac[i]=fac[i-1]*i%p;
facinv[mx]=ksm(fac[mx],p-2);
for(int i=mx-1;i;i--)facinv[i]=facinv[i+1]*(i+1)%p;
return;
}
inline int C(int x,int y)
{
return fac[x]*facinv[y]%p*facinv[x-y]%p;
}
inline void workz()
{
for(int i=0;i<P;i++)
{
int now=(pw[P]-1)^pw[i];
for(int j=now;j;j=now&(j-1))
{
t[j|pw[i]]+=t[j];
if(t[j|pw[i]]>=p)t[j+pw[i]]-=p;
}
t[pw[i]]+=t[0];
if(t[pw[i]]>=p)t[pw[i]]-=p;
}
return;
}
inline void workf()
{
for(int i=0;i<P;i++)
{
int now=(pw[P]-1)^pw[i];
for(int j=now;j;j=now&(j-1))
{
t[j|pw[i]]-=t[j];
if(t[j|pw[i]]<0)t[j+pw[i]]+=p;
}
t[pw[i]]-=t[0];
if(t[pw[i]]<0)t[pw[i]]+=p;
}
return;
}
signed main()
{
freopen("kor.in","r",stdin);
freopen("kor.out","w",stdout);
T=read();pre(100000);
while(T--)
{
memset(t,0,sizeof(t));
n=read();k=read();r=read();
for(int i=1;i<=n;i++)
{
a[i]=read();t[a[i]]++;
}
workz();
for(int i=0;i<pw[P];i++)
{
t[i]=C(t[i],k);
}
workf();
printf("%lld\n",t[r]);
}
return 0;
}

浙公网安备 33010602011771号