20170927 随单题
随:
50%有一个dp:
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
#define MAXN 100005
#define re register
ll n,m,p,a[MAXN],num[MAXN],order[MAXN],tot=0,f[2][MAXN],ans=0,den;
const ll mod=1e9+7;
inline ll q_pow(re ll a,re ll b,re ll p){
re ll res=1;
while(b){
if(b&1) res=(res*a)%p;
a=(a*a)%p;
b>>=1;
}
return res%p;
}
signed main(){
scanf("%lld%lld%lld",&n,&m,&p);
if(n==1){
re ll b;
scanf("%lld",&b);
re ll ans=q_pow(b,m,p)%mod;
printf("%lld\n",ans);
return 0;
}
if(p==2){
puts("1");
return 0;
}
for(ll i=1;i<=n;i++){
scanf("%lld",&a[i]);
if(num[a[i]]==0) order[++tot]=a[i];
num[a[i]]++;
}
f[0][1]=1;
for(ll i=1;i<=m;i++){
for(ll j=1;j<=p;j++)
f[i&1][j]=0;
for(ll j=1;j<=tot;j++){
ll ord=order[j];
ll q=num[ord];
for(ll k=1;k<p;k++)
f[i&1][ord*k%p]=(f[i&1][ord*k%p]+f[i&1^1][k]*q)%mod;
}
}
den=q_pow(n,mod-2,mod);
den=q_pow(den,m,mod);
for(ll i=1;i<p;i++)
ans=(ans+f[m&1][i]*i)%mod;
//printf("%lld %lld\n",ans,den);
printf("%lld\n",ans*den%mod);
return 0;
}
100%:原根+瞎搞?
其实不用怎么做(明明是博主不会原根)
我们倍增优化这个dp,将m二进制拆分
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
#define MAXN 100005
#define re register
ll n,m,p,a[MAXN],f[2][1005],ans=0,den,g[2][1005],nowg=1,nowf=1;
const ll mod=1e9+7;
inline ll q_pow(re ll a,re ll b,re ll p){
re ll res=1;
while(b){
if(b&1) res=(res*a)%p;
a=(a*a)%p;
b>>=1;
}
return res%p;
}
signed main(){
scanf("%lld%lld%lld",&n,&m,&p);
if(n==1){
re ll b;
scanf("%lld",&b);
re ll ans=q_pow(b,m,p)%mod;
printf("%lld\n",ans);
return 0;
}
if(p==2){
puts("1");
return 0;
}
for(ll i=1;i<=n;i++){
scanf("%lld",&a[i]);
f[0][a[i]]++;
}
den=q_pow(n,mod-2,mod);
den=q_pow(den,m,mod);
g[0][1]=1;
while(m){
if(m&1){
for(ll i=0;i<=p;i++)
g[nowg][i]=0;
for(ll i=1;i<p;i++){
for(ll j=1;j<p;j++)
g[nowg][i*j%p]=(g[nowg][i*j%p]+f[nowf^1][i]*g[nowg^1][j])%mod;
}
nowg^=1;
}
for(ll i=0;i<=p;i++)
f[nowf][i]=0;
for(ll i=1;i<p;i++){
for(ll j=1;j<p;j++)
f[nowf][i*j%p]=(f[nowf][i*j%p]+f[nowf^1][i]*f[nowf^1][j])%mod;
}
nowf^=1;
m>>=1;
}
for(ll i=1;i<p;i++)
ans=(ans+g[nowg^1][i]*i)%mod;
//printf("%lld %lld\n",ans,den);
printf("%lld\n",ans*den%mod);
return 0;
}
单:
40%:n2暴力+n3高斯消元
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
#define MAXN 100005
#define re register
#define eps (1e-8)
using namespace std;
ll t,n,type,a[MAXN],b[MAXN];
bool flag=1;
ll to[MAXN<<1],nxt[MAXN<<1],pre[MAXN],cnt=0;
inline void add(re ll u,re ll v){
cnt++,to[cnt]=v,nxt[cnt]=pre[u],pre[u]=cnt;
}
ll f[MAXN][20],deep[MAXN];
inline void dfs(re ll x){
for(re ll i=1;i<=18;i++){
if(f[x][i-1])
f[x][i]=f[f[x][i-1]][i-1];
}
for(re ll i=pre[x];i;i=nxt[i]){
if(to[i]!=f[x][0]){
deep[to[i]]=deep[x]+1;
f[to[i]][0]=x;
dfs(to[i]);
}
}
}
inline ll LCA(re ll x,re ll y){
if(deep[x]<deep[y]) swap(x,y);
re ll k=deep[x]-deep[y];
for(re ll i=0;i<=18;i++)
if((1<<i)&k)
x=f[x][i];
if(x==y) return x;
for(re ll i=18;i>=0;i--)
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
return f[x][0];
}
double g[10005][10005];
inline void gs(){
for(re ll i=1;i<=n;i++){
re ll p=i;
for(re ll j=i+1;j<=n;j++)
if(fabs(g[j][i])>fabs(g[p][i]))
p=j;
for(re ll j=1;j<=n+1;j++)
swap(g[p][j],g[i][j]);
if(fabs(g[i][i])<eps) continue;
double tmp=g[i][i];
for(re ll j=1;j<=n+1;j++)
g[i][j]/=tmp;
for(re ll j=1;j<=n;j++)
if(i!=j){
double temp=g[j][i];
for(re ll k=1;k<=n+1;k++)
g[j][k]-=g[i][k]*temp;
}
}
}
signed main(){
scanf("%lld",&t);
while(t--){
scanf("%lld",&n);
for(re ll i=1,u,v;i<n;i++){
scanf("%lld%lld",&u,&v);
if(v!=u+1) flag=0;
add(u,v),add(v,u);
}
dfs(1);
scanf("%lld",&type);
if(type==0){
for(re ll i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
for(re ll i=1;i<=n;i++){
for(re ll j=1;j<=n;j++){
if(i==j){
continue;
}
re ll lca,dis;
if(flag==1)
dis=abs(i-j);
else{
lca=LCA(i,j);
dis=deep[i]+deep[j]-2*deep[lca];
}
b[i]+=a[j]*dis;
}
printf("%lld ",b[i]);
}
puts("");
}else{
for(re ll i=1;i<=n;i++){
scanf("%lld",&b[i]);
g[i][n+1]=(double)b[i];
}
for(re ll i=1;i<=n;i++){
for(re ll j=1;j<=n;j++){
if(i==j){
g[i][j]=0;
continue;
}
re ll lca,dis;
if(flag==1)
dis=abs(i-j);
else{
lca=LCA(i,j);
dis=deep[i]+deep[j]-2*deep[lca];
//printf("%lld %lld\n",lca,dis);
}
g[i][j]=(double)dis;
}
}
gs();
for(re ll i=1;i<=n;i++){
//if(fabs(g[i][n+1])<eps) printf("0 ");
//else
printf("%.0lf ",g[i][n+1]);
}
puts("");
}
memset(f,0,sizeof(f));
memset(pre,0,sizeof(pre));
//memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
cnt=deep[1]=0;
flag=1;
}
return 0;
}
/*
7
1 2
1 3
2 4
2 5
4 6
4 7
10
5
1 2
1 3
2 4
2 5
0
6 8 7 1 3
5
1 2
1 3
2 4
2 5
1
23 24 34 47 43
5
1 2
1 3
2 4
2 5
0
19 2 1 14 3
5
1 2
1 3
2 4
2 5
1
37 38 74 49 71
4
1 2
2 3
3 4
0
5 7 10 8
4
1 2
2 3
3 4
1
51 31 25 39
6
1 2
1 3
1 4
2 5
2 6
0
5 7 9 1 3 2
6
1 2
1 3
1 4
2 5
2 6
1
27 30 36 52 51 53
*/
100%:我能不能不在这里推式子呀?毕竟把别人提解粘过来不太好
那我就放个链接把大家骗到小红博客里:
https://www.cnblogs.com/Rorschach-XR/p/11255318.html
rp++
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
#define MAXN 100005
#define re register
using namespace std;
ll t,n,type,a[MAXN],b[MAXN];
ll to[MAXN<<1],nxt[MAXN<<1],pre[MAXN],cnt=0;
inline void add(re ll u,re ll v){
cnt++,to[cnt]=v,nxt[cnt]=pre[u],pre[u]=cnt;
}
ll deep[MAXN],sum=0,size[MAXN];//size[i]表示i的子数中a[son]的和
void dfs_1(re ll x,re ll fa){
for(ll i=pre[x];i;i=nxt[i]){
ll y=to[i];
if(y==fa) continue;
deep[y]=deep[x]+1;
dfs_1(y,x);
size[x]+=size[y];
}
}
void dfs_2(re ll x,re ll fa){
for(re ll i=pre[x];i;i=nxt[i]){
re ll y=to[i];
if(y==fa) continue;
b[y]=b[x]+sum-2*size[y];
dfs_2(y,x);
}
}
ll dt[MAXN];
void dfs_3(re ll x,re ll fa){
for(re ll i=pre[x];i;i=nxt[i]){
re ll y=to[i];
if(y==fa) continue;
dt[y]=b[y]-b[x];
dfs_3(y,x);
}
}
void dfs_4(re ll x,re ll fa){
a[x]=size[x];
for(re ll i=pre[x];i;i=nxt[i]){
re ll y=to[i];
if(y==fa) continue;
dfs_4(y,x);
a[x]-=size[y];
}
}
signed main(){
scanf("%lld",&t);
while(t--){
scanf("%lld",&n);
for(re ll i=1,u,v;i<n;i++){
scanf("%lld%lld",&u,&v);
add(u,v),add(v,u);
}
scanf("%lld",&type);
if(type==0){
for(re ll i=1;i<=n;i++){
scanf("%lld",&a[i]);
sum+=a[i];
size[i]=a[i];
}
dfs_1(1,0);
for(re ll i=1;i<=n;i++)
b[1]+=deep[i]*a[i];
dfs_2(1,0);
for(re ll i=1;i<=n;i++)
printf("%lld ",b[i]);
puts("");
}else{
for(re ll i=1;i<=n;i++){
scanf("%lld",&b[i]);
}
dfs_3(1,0);
for(re ll i=1;i<=n;i++)
sum+=dt[i];
size[1]=(sum+2*b[1])/(n-1);
for(re ll i=2;i<=n;i++)
size[i]=(size[1]-dt[i])/2;
dfs_4(1,0);
for(re ll i=1;i<=n;i++)
printf("%lld ",a[i]);
puts("");
}
memset(pre,0,sizeof(pre));
memset(deep,0,sizeof(deep));
memset(size,0,sizeof(size));
memset(dt,0,sizeof(dt));
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
cnt=sum=0;
}
return 0;
}
/*
7
1 2
1 3
2 4
2 5
4 6
4 7
10
5
1 2
1 3
2 4
2 5
0
6 8 7 1 3
5
1 2
1 3
2 4
2 5
1
23 24 34 47 43
5
1 2
1 3
2 4
2 5
0
19 2 1 14 3
5
1 2
1 3
2 4
2 5
1
37 38 74 49 71
4
1 2
2 3
3 4
0
5 7 10 8
4
1 2
2 3
3 4
1
51 31 25 39
6
1 2
1 3
1 4
2 5
2 6
0
5 7 9 1 3 2
6
1 2
1 3
1 4
2 5
2 6
1
27 30 36 52 51 53
*/
题:
3个组合数(CATALAN相关)和一个dp
#include<cstdio>
#include<iostream>
#include<cmath>
#define ll long long
#define mod 1000000007
#define MAXN 100005
using namespace std;
ll n,type,ans=0,dp[MAXN]={1};
ll q_pow(ll a,ll b,ll p){
ll res=1;
while(b){
if(b&1) res=(res*a)%p;
a=(a*a)%p;
b>>=1;
}
return res;
}
ll fac[MAXN],inv[MAXN];
void get_fac_and_inv(){
fac[0]=fac[1]=inv[0]=inv[1]=1;
for(ll i=2;i<=n;i++)
fac[i]=fac[i-1]*i%mod;
inv[n]=q_pow(fac[n],mod-2,mod);
for(ll i=n-1;i>=2;i--)
inv[i]=inv[i+1]*(i+1)%mod;
}
void dfs(ll now,ll num){
if(num==n&&now==0){
ans++;
if(ans>mod) ans-=mod;
//cout<<ans<<endl;
return ;
}
if(num==n&&now!=0) return ;
if(abs(now)>(n>>1)) return ;
if(abs(now)>(n-num)) return ;
dfs(now+1,num+1);
dfs(now-1,num+1);
}
ll C(ll n,ll m){
return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
ll CATALAN(ll n){
return C(2*n,n)*q_pow(n+1,mod-2,mod)%mod;
}
int main(){
scanf("%lld%lld",&n,&type);
get_fac_and_inv();
if(type==0){
ll m=n>>1;
for(ll i=0;i<=m;i++){
ll j=m-i;
ans=(ans+(fac[n]*inv[i]%mod*inv[j]%mod*inv[i]%mod*inv[j]%mod)%mod)%mod;
}
printf("%lld\n",ans%mod);
}
if(type==1){
ll m=n>>1;
ll invm=q_pow(m+1,mod-2,mod);
ans=fac[n]*inv[m]%mod*inv[m]%mod*invm%mod;
printf("%lld\n",ans%mod);
}
if(type==2){
dp[1]=dp[0]*4;
for(ll i=2;i<=n/2;i++)
for(ll j=1;j<=i;j++)
dp[i]=(dp[i]+dp[i-j]%mod*CATALAN(j-1)%mod*4%mod)%mod;
printf("%lld\n",dp[n/2]%mod);
}
if(type==3){
for(ll i=0;i<=n;i+=2)
ans=(ans+C(n,i)%mod*CATALAN(i/2)%mod*CATALAN((n-i)/2))%mod;
printf("%lld\n",ans%mod);
}
return 0;
}

浙公网安备 33010602011771号