基本计数方法专题

例题

UVA 11401 Triangle Counting

题意:在1..n中取三个不同的整数,使其恰能构成3角形三边长,求取法数

枚举最大的边x,假设其中一条边为y,另一条边的取值范围是 (xy,x) ,共y-1个解,总数为 (x1)(x2)/2
去掉y=z的三角形 x1x/2 个,除2排除 y<z

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[i]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
ll f[1000000+10];

int main()
{
//  freopen("uva11401.in","r",stdin);
//  freopen(".out","w",stdout);

    MEM(f)
    Fork(i,4,1000000)   
        f[i] = f[i-1] + ((ll)(i-1)*(i-2)/2-(ll)(i-1)/2)/2;
    int n;
    while(cin>>n) {
        if (n<3) break;
        cout<<f[n]<<endl;
    }

    return 0;
}

UVA 11806 Cheerleaders

题意:在一个n*m的矩形网格里放k个石子(每个格子最多放一个),使得最外边的每1行/列都至少有一个石子,有多少放法?
容斥

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (1000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[i]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
ll C[510][510]={0};
int main()
{
//  freopen("uva11806.in","r",stdin);
//  freopen(".out","w",stdout);
    C[0][0]=1;
    For(i,505) {
        C[i][0]=1;
        For(j,i) C[i][j] =add( C[i-1][j],C[i-1][j-1]);
    }
    int T=read();
    For(kcase,T) {
        ll ans=0;
        int m=read(),n=read();
        int k=read();
        Rep(S,16) {
            int b=0;
            int r=m,c=n;
            if (S&1) {r--; b^=1;}
            if (S&2) {r--; b^=1;}
            if (S&4) {c--; b^=1;}
            if (S&8) {c--; b^=1;}
            if (!b) ans=add(ans,C[r*c][k]);
            else ans=sub(ans,C[r*c][k]);
            ans%=F;
        }
        Pr(kcase,ans)
    }

    return 0;
}

LA 3516 Exploring Pyramids

题意:给一个树的dfs序列,某些节点具有相同的编号,问有多少棵树能与之队应(假设树为多叉树,每个节点的任意2子节点左右之分,dfs序优先向左走)

区间dp

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (1000000000)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[i]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
#define MAXN (300+10)
char s[MAXN];
int n;
ll dp[MAXN][MAXN];
ll f(ll a,ll b){
    if (a==b) return 1;
    if (s[a]!=s[b]) return 0;
    if (dp[a][b]!=-1) return dp[a][b];

    dp[a][b] = 0;
    Fork(k,a+2,b) {
        upd(dp[a][b] , mul(f(a+1,k-1) , f(k,b)));
    }
    return dp[a][b];
}
int main()
{
//  freopen("la3516.in","r",stdin);
//  freopen(".out","w",stdout);
    while (cin>>s) {
        memset(dp,-1,sizeof(dp));
        int n=strlen(s);
        cout<<f(0,n-1)<<endl;

    }


    return 0;
}

UVA 11361 Investigating Div-Sum Property

题意:已知正整数a,b,k,求有多少整数n满足 anb,k|n,k|(n)
1a,b232,1k<10000

数位dp,注意 k100 的时候答案必为0

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (k)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[i]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
typedef long long ll;
typedef unsigned long long ull;

ll a,b;
ll k;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
//ll sub(ll a,ll b){if (a>=b) return (a-b)%F; else return (((b-a)%F) ==0 )? 0 : F-1-(b-a)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
ll t10[15];
ll dp[15][105][105];
ll f(int d,ll m1,ll m2) {
//  cout<<d<<m1<<m2<<endl;
    if (!d) {
        if (m1==0 && m2==0) return 1;
        return 0;
    }
    if (dp[d][m1][m2]!=-1) {
        return dp[d][m1][m2];
    }

    ll ans=0;
    Rep(x,10) {
        ans+= f(d-1,sub(m1,x),sub(m2,mul(x,t10[d-1])));
    }
    dp[d][m1][m2]=ans;
    return ans;
}
int len;
char s[100];
ll dfs(int i,ll m1,ll m2) {
    if (i==len) {
        return f(0,m1,m2);
    }
    ll ans=0;
    Rep(j,s[i]-'0') {
        ans+=f(len-i-1,sub(m1,j),sub(m2,mul(t10[len-i-1],j)) );
    }
    ans+=dfs(i+1,sub(m1,s[i]-'0'),sub(m2,t10[len-i-1]*(s[i]-'0')%F ) );
    return ans;
}
void to_s(ll a) {
    stringstream ss;
    ss<<a;
    ss>>s;
    len=strlen(s);
    return;
}
int main()
{
//  freopen("uva11361.in","r",stdin);
//  freopen(".out","w",stdout);
    t10[0]=1;
    For(i,14) {
        t10[i]=t10[i-1]*10;
    }
    int T=read();
    while(T--) {
        memset(dp,-1,sizeof(dp));
        cin>>a>>b>>k;
        if (k>=100) {
            puts("0"); continue;
        }
        to_s(b);
        ll ans=0;
        ans+=dfs(0,0,0);
        to_s(a-1);
        ans-=dfs(0,0,0);
        cout<<ans<<endl; 
    }   

    return 0;
}

LA 4123 Glenbow Museum

题意:对于一个边平行于坐标轴的多边形,我们可以用一个由R和O组成的序列来描述它:从某个顶点开始按照逆时针顺序走,碰到一个90°的内角记R;碰到一个270°的内角记O。这样的序列称为角度序列。定义星型多边形为多边形中存在一个点可以看到多边形边界上每一个点。现在给定正整数n,求有多少个长度为L的角度序列至少可以对应一个星型多边形。其中多边形的每条边长任意。

本题等价于:长度为L的序列,要求序列中只有O和R,且R比O多4个,且头尾不能同位O,且不能有连续2个O出现,问符合条件的序列数

考虑R有4个,OR有p-4个,其排成的不同序列的个数为 C4p
再考虑 RO 的序列数,刚好是 OR 的序列数 C4p1
注意奇数和n<4时答案为0

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[i]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
#define MAXN (1000+10)

int main()
{
//  freopen("la4123.in","r",stdin);
//  freopen(".out","w",stdout);
    int n;
    int kcase=0;
    while (cin>>n &&n){
        ll ans=0;
        if (n<4||n%2==1) {
            Pr(++kcase,0) continue;
        }
        ll p=(n-4)/2+4;

        ans = p*(p-1)*(p-2)*(p-3)/4/3/2;
        if (p>4) ans+=(p-1)*(p-2)*(p-3)*(p-4)/4/3/2;
        Pr(++kcase,ans)
    }   


    return 0;
}

UVA 10253 Series-Parallel Networks

题意:有一个n条边的串并联网络,
2个串并联网络,串的顺序调换,并的顺序调换,视为相同
问满足题意的网络有几个?
1n30

考虑树dp,
假设这个串并联网络最后一次是串还是并,考虑所有边数划分方案

注意:必须划分成至少2部分(不然不算串并)

可重复选择元素的组合数
设第i个元素选xi个,答案为 x1+x2++xn=k 的非负元素的解的个数,积 y1+y2++yn=n+k 的正整数解个数,隔板法即可

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[i]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
ll C(ll n,ll m) {
    double ans=1;
    Rep(i,m) ans*=n-i;
    For(i,m) ans/=i;
    return (ll)(ans+0.5);
}
#define MAXN (35)
ll f[MAXN],d[MAXN][MAXN];
ll calc(int i,int j) { // 子树的叶子最多i个, j个叶子 
    if (d[i][j]!=-1) return d[i][j];
    d[i][j]=0;
    for(int p=0;j-p*i>=0;p++) {
        d[i][j] += C(f[i]+p-1,p)*calc(i-1,j-i*p);
    }
    return d[i][j];
}
int main()
{
//  freopen("uva10253.in","r",stdin);
//  freopen(".out","w",stdout);
    memset(d,-1,sizeof(d));
    d[0][0]=1;
    For(i,30) d[i][0]=1,d[0][i]=0;

    f[1]=1;
    For(i,29) {
        f[i+1] = calc(i,i+1);
    }
    int n;
    while(cin>>n &&n) {
        if (n==1) puts("1");
        else cout<<2*f[n]<<endl;
    }   

    return 0;
}

习题

UVA 11038 How many 0’s?

题意:求m~n的所有整数中0出现的次数

不要数位dp,
考虑第i位为0的数在0~n中出现的次数

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[i]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
ll calc(ll n){
    if (n<0) return 0;
    ll ans=1; //把0算上 
    ll Left=n,Right=0,j=1;
    while(Left) {
        int p=Left%10; Left/=10;
        if (p) ans += Left*j;
        else ans += (Left-1)*j + Right+1;

        Right += j*p;
        j*=10;
    }
    return ans;
}
int main()
{
//  freopen("uva11038.in","r",stdin);
//  freopen(".out","w",stdout);

    ll m,n;
    while (cin>>m>>n && (m>=0) && (n>=0)) {
        cout<<calc(n)-calc(m-1)<<endl;

    }


    return 0;
}

UVA 10883 Supermean

题意:给n个数,每相邻两个数求平均数得到n-1个数,重复操作得到n-2个数……,最后得到1个数,求这个数。

二项式系数
乘法取log

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[i]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
int n;
void work() {
    double p=0;

    double p2=-(double)(n-1)*log(2);
    double ans=0;

    double c;
    Rep(i,n) {
        scanf("%lf",&c);
        ans += exp(p+p2)*c;
        p+=log((double)n-i-1)-log((double)i+1);
    }
    printf("%.3lf\n",ans);
}
int main()
{
//  freopen("uva10883.in","r",stdin);
//  freopen(".out","w",stdout);

    int T=read();
    For(kcase,T) {
        printf("Case #%d: ",kcase);
        n=read();
        work();
    }

    return 0;
}

UVA 1510 Neon Sign

题意:n个点两两连边,已知没条边的颜色(只有2种),求单色三角形数。

经典做法

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[i]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
#define MAXN (1000+10)
ll deg[MAXN];
int main()
{
//  freopen("uva1510.in","r",stdin);
//  freopen(".out","w",stdout);

    int T=read();
    while(T--) {
        int n=read();
        MEM(deg)
        For(i,n-1) 
            Fork(j,i+1,n) {
                int p=read();
                if (p) deg[i]++,deg[j]++; 
            }
        ll ans=0;
        For(i,n) ans += deg[i]*(n-1-deg[i]);
        cout<< (ll)n*(n-1)*(n-2)/6 -ans/2<< endl;
    }


    return 0;
}

UVA 1393 Highway, CERC 2006

题意:n行m列的点阵,有多少条非水平非竖直的直线穿过点阵中至少2个点?
令f[i][j]表示 (0,0)>(n,m) 经过的直线是否符合条件,但是2倍的地方要减回去
然后求2次二维前缀和就是答案。

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[i]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
int gcd(int a,int b){if (!b) return a;return gcd(b,a%b);}
ll f[350][350];
int main()
{
//  freopen("uva1393.in","r",stdin);
//  freopen(".out","w",stdout);

    MEM(f) 
    For(i,300) For(j,300) {
        if (gcd(i,j)==1) f[i][j]=1;
        else if (gcd(i,j)==2) f[i][j]=-1; 
    }
    For(i,300) For(j,300) {
        f[i][j] += f[i][j-1] + f[i-1][j] - f[i-1][j-1]; 
    } 
    For(i,300) For(j,300) {
        f[i][j] += f[i][j-1] + f[i-1][j] - f[i-1][j-1]; 
    } 

    int n,m;
    while(cin>>n>>m && n) cout<<f[n-1][m-1]*2<<endl;


    return 0;
}

UVA 10237 Bishops

题意:在n*n的棋盘上放k个互不攻击的象的方案数。两个象不攻击当且仅当它们不处于同一斜线上

把棋盘旋转45度,然后乱搞

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[i]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
#define MAXN (70+10)
int n;
ll f[MAXN][MAXN],g[MAXN][MAXN];
void work(int n,int k) {
    MEM(f) f[0][0]=1;
    For(i,n) f[i][0]=1;
    For(i,n) 
        For(j,k) {
            int len=(i+1)/2*2 -1;
            f[i][j] = f[i-1][j] + f[i-1][j-1] * (len-j+1); 
        }

    MEM(g) g[0][0]=1;
    For(i,n) g[i][0]=1;
    For(i,n) 
        For(j,k) {
            int len=(i+1)/2*2 ;
            g[i][j] = g[i-1][j] + g[i-1][j-1] * (len-j+1); 
        }
}
int main()
{
//  freopen("uva10237.in","r",stdin);
//  freopen(".out","w",stdout);
    int n,k;
    work(30,30);
    while(cin>>n>>k&& n) {

        ll ans=0;
        Rep(i,k+1) ans += f[n][i] * g[n-1][k-i];
        cout<<ans<<endl; 
    }


    return 0;
}

3.13补充

极角排序流

UVA 11529 Strange Tax Calculation

题意:给n个点,无三点共线,随机取3个点构成一个三角形,问其中包含的点的个数的期望。

LA 4064 Magenetic Train Tracks ,Dhaka 2007

题意:给n个点,无三点共线,问构成的直角和锐角三角形的个数。

n1200

2题很类似所以放一起,
大致都是枚举一个点,然后以这个点为准对剩下的点极角排序,最后转一圈,用单调队列(或者说双指针)统计

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("City %d: %.2lf\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[i]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#define pi (3.14159265358579)
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
#define MAXN (6000+10)
pair<double,double> p[MAXN];
double ang(pair<double,double> p,pair<double,double> p2) {return atan2(p2.se-p.se,p2.fi-p.fi); }

int kcase=0,n;
double r[MAXN];
int main()
{
//  freopen("uva11529.in","r",stdin);
//  freopen(".out","w",stdout);

    while(cin>>n && n)
    {
        For(i,n) cin>>p[i].fi>>p[i].se;
        ll ans=0;
        For(i,n) {
            int m=0;
            For(j,n)
                if (j^i)
                    Rep(k,2) r[++m]=pi*k*2+ang(p[i],p[j]);
            sort(r+1,r+m+1);
            int mv=1;
            For(j,n-1) {
                while (r[mv]<r[j]+pi) ++mv;
                int cnt=mv-j-1;
                ans += (ll) cnt *(cnt-1) / 2;
            }


        }
        Pr(++kcase,((double)n*(n-1)*(n-2)*(n-3)/6-(double)ans)/n/(n-1)/(n-2)*6);
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define eps (1e-9)
#define vi vector<int> 
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Scenario %d:\nThere are %lld sites for making valid tracks\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[i]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#define pi (acos(-1.0))
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
ll gcd(ll a,ll b){if (!b) return a ; return gcd(b,a%b);}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
#define MAXN (4000+10)
pair<ll,ll> p[MAXN];
double ang(pair<ll,ll> p,pair<ll,ll> p2) { return atan2((double)p2.se-p.se,(double)p2.fi-p.fi); }

int kcase=0,n;
double r[MAXN];
int main()
{
//  freopen("la4064.in","r",stdin);
    while(cin>>n && n)
    {
        For(i,n) cin>>p[i].fi>>p[i].se;
        ll ans=0;
        For(i,n) {
            int m=0;
            For(j,n)
                if (j^i)
                    Rep(k,2) r[++m]=pi*k*2+ang(p[i],p[j]);
            sort(r+1,r+m+1);
            int mv=1,mv2=1;
            For(j,n-1) {
                while (r[mv]<=r[j]+pi/2-eps) ++mv;
                while (r[mv2]<r[j]+pi) ++mv2;
                int cnt=mv2-mv;
                ans += cnt;
            }
        }
        Pr(++kcase,((ll)(n-1)*(n-2)*n/6-ans));
    }
//  {
//      freopen("la4064_makedata.in","w",stdout);
//      cout<<"100"<<endl;
//      For(i,100) {
//          int a=rand()%10000,b=rand()%10000;
//          if (gcd(a,b)==1) cout<<a<<' '<<b<<endl; else i--;
//      }
//      cout<<"0\n";
//              
//  }
    return 0;
}

LA 5092 Permutation Counting, Harbin 2010

题意:1~n的排列 (a1,,an) ,恰有k个位置 ai>i ,已知 n ,求方案数
n1000
dp题,首先很容易想出递推式
f(n,k)=(k+1)f(n1,k)+(nk)f(n1,k1)
打表发现

n \ m 0 1 2 3 4 5 6 7 8
1 1
2 1 1
3 1 4 1
4 1 11 11 1
5 1 26 66 26 1
6 1 57 302 302 57 1
7 1 120 1191 2416 1191 120 1
8 1 247 4293 15619 15619 4293 247 1
9 1 502 14608 88234 156190 88234 14608 502 1

就是欧拉数wiki链接

不过讲道理打表都能直接过了DAZE

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (1000000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[i]<<endl;
#define PRi2D(a,n,m) Rep(i,n) { \
                        Rep(j,m) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
#define MAXN (2000)
ll f[MAXN][MAXN]={0};
int main()
{
//  freopen("uva1485.in","r",stdin);
    For(i,1000)
    {
        f[i][0]=1;
        For(j,i) {
            f[i][j]=add( mul(f[i-1][j], j+1) , mul( f[i-1][j-1] , i-j) );
        }
    }
//  PRi2D(f,10,10);
    int n,k;
    while(cin>>n>>k)
        cout<<f[n][k]<<endl;
    return 0;
}

UVA 11139 Counting Quadrilaterals

题意:求n*n的网格图(n+1行点),可以连出多少网格四边形(n<=120)
SP:本题允许O(n^4)做法

根据前面几题的做法
求总数,3点共线的情况,4点共线的情况,凹4边形(三角形里含一个点)的情况,容斥

Pick定理:格点多边形面积=内部整点数+1-边上整点数/2

cnta,b 表示外接矩形为a*b的三角形,内部的点的和

在平面上随机取3个整点构成的三角形,一定有一个点最靠边(横纵坐标均在其它2点的同侧
所以可以枚举这个点并通过水平对称,垂直对称,遍历所有整点3角形(会有重复的)

凹四边形的解法,假设(0,0)O点选,枚举另外2点(假设在右下侧),且是向左拐的(有向面积 >0),然后我们得到了一个三角形,
接下来考虑如何不重不漏

情况情况计入
两条边平行x,y轴,有3个靠边点∠O为锐角2次,直角1次需要计入4次
恰有一条边平行x,y轴的三角形,若为等腰三角形则这条边不是底边,2个靠边点2次需要计入4次
恰有一条边平行x,y轴的三角形,且这条边为等腰三角形的底边,2个靠边点1次需要计入2次
没有一条边平行x,y轴的三角形,有2个靠边点2次需要计入4次
没有一条边平行x,y轴的三角形,有1个靠边点1次需要计入4次
#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[i]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}  
ll C(ll n,ll m) {
    if (n==m||0==m) return 1;
    if (n<m) return 0;
    ll p=1;
    Rep(i,m) p=p*(n-i)/(i+1);
    return p; 
}
#define MAXN (130) 
ll g[MAXN][MAXN]={0};
int ABS(int a){
    if (a>0) return a;return -a;
}
ll gcd(ll a,ll b){if (!b) return a;return gcd(b,a%b);}
ll calc(int a,int b,int c,int d){
    ll S = (a*d-b*c)/2;
    if(S<0) S=-S;
    ll B = g[a][b] + g[c][d] + g[ABS(a-c)][ABS(b-d)];
    return S + 1 - B /2;
}
ll cnt[MAXN][MAXN]={0}; // 表示长宽为i,j的矩形的所有内接三角形的里面的点的个数和 
const int maxn = 122;
ll work() {
    Rep(i,122)
        Rep(j,122)
            g[i][j]=gcd(i,j);   
    Rep(i,maxn)
        Rep(j,maxn)
            Rep(k,maxn) 
                Rep(l,maxn) {
                    if (j*k-i*l<=0) break;
                     int a=max(i,k),b=max(j,l);
                     ll tmp=calc(i,j,k,l);
                     ll p;
                     if (i==0 || k==0) {
                        if (j!=l) p=2;
                        else p=1;
                     }else if (j==0 || l==0) {
                        if (i!=k) p=2;
                        else p=1;
                     } else if ((i==a && j== b) || (k == a && l == b)) p=2;
                     else p=4;
                     cnt[a][b]+=tmp*p;
                }
}

int n;
int main()
{
//  freopen("uva11139.in","r",stdin);
//  freopen(".out","w",stdout);
    work();
    while(cin>>n&&n) {
        n++;
        ll ans=C(n*n,4)-2LL*C(n,3)*n*(n*n-3)+3LL*2*C(n,4)*n;
        For(i,n-1) For(j,n-1) {
            ans -= (ll)2LL* (g[i][j]-1) * (n-i)*(n-j)*(n*n-3);
            ans += (ll)3LL* 2 * C(g[i][j]-1,2) * (n-i)*(n-j);
        }
        For(i,n-1) For(j,n-1)
            ans += 2LL*cnt[i][j]*(n-i)*(n-j);
        printf("%d %lld\n",n-1,ans);
    }   


    return 0;
}

UVA 1425 Metal

题意:平面上有n 50 个点,每个点x坐标不同,统计有多少种方法把它们连成一个单调多边形,单调多边形是指,如果把多边形看成实心物体,该物体任意竖线的相交部分是单点或一条线段。

从左往右枚举
状态用最后一个点与之前某个点相连转移

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[i]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
#define MAXN (60)
class P{
public:
    ll x,y;
    P(ll x=0,ll y=0):x(x),y(y){}
    friend ll Cross(P A,P B) {return A.x*B.y-A.y*B.x;  }
    friend P operator- (P A,P B) { return P(A.x-B.x,A.y-B.y); }
    friend bool operator<(P a,P b){return a.x<b.x;  }

}p[MAXN]; 
int dp[MAXN][MAXN],n;
ll sgn(ll x){ return (!x)?(0):((x>0)?1:-1);} 
int judge(int i,int j){ //i+1..j这段的折线 是否与线段i,j+1相交 
    int sg=sgn(Cross(p[j+1]-p[i],p[i+1]-p[i]));
    Fork(k,i+1,j-1)
        if (sg!=sgn(Cross(p[j+1]-p[i],p[k+1]-p[i]))) return 0;
    return sg; //0 不合法  
} 
ll solve() {
    MEM(dp)
    dp[1][2]=dp[2][1]=1;
    For(i,n) {
        int k=i-1;
        For(j,k-1) {
            dp[i][j] +=dp[k][j];
            dp[j][i] +=dp[j][k];
            int p=judge(j,k);
            if (p==1) dp[k][i] +=dp[k][j];
            if (p==-1) dp[i][k] +=dp[j][k];
        }       

    }

    ll ans=0;

    For(i,n) {
        int p=judge(i,n-1);
        if (p==1) ans+=dp[n][i];
        if (p==-1) ans+=dp[i][n];
    }
    return ans;
}

int main()
{
//  freopen("uva1425.in","r",stdin);
//  freopen(".out","w",stdout);

    int T=read();
    while(T--) {
        n=read();   
        For(i,n) cin>>p[i].x>>p[i].y;
        sort(p+1,p+1+n);
        cout<<solve()<<endl;
    }



    return 0;
}

HDU 3723 Delta Wave, Tianjin 2010

有一条折线,起点(0,0),终点(n,0),每向右延伸一个单位长度,高度要么加1,要么减一,要么不变,问符合条件的线段数量?

import java.io.*;
import java.util.*;
import java.math.*;

public class Main
{
    public static void main(String args[])
    {
        Scanner cin = new Scanner(System.in);
        int n;

        while(cin.hasNextInt())
        {
            n = cin.nextInt();
            BigInteger ans = BigInteger.ONE;
            BigInteger tmp=BigInteger.ONE;  
            for(int i=0;i<n/2;i++) {
                tmp=tmp.multiply(BigInteger.valueOf(n-2*i)).multiply(BigInteger.valueOf(n-2*i-1))
                .divide(BigInteger.valueOf(i+1)).divide(BigInteger.valueOf(i+2));
                ans=ans.add(tmp);
            }
            System.out.println(ans.mod(BigInteger.TEN.pow(100)));
        }
    }
}

25补题

LA 3357,UVA 1350 Pinary, Seoul 2005

2进制中没有连续1的正整数,第 2<k<9107 大是多少?
找规律,发现长度为l且2进制中没有连续1的正整数恰有fib(l)个,
然后贪心每次贪最高位就行。
注意LA上java要快速输出不然会T
PS:UVA上Submission error 不知道为什么

import java.io.*;
import java.util.*;
public class Main
{
    private static Writer writer = null;  

    public static void main(String args[])
    {
        Scanner cin = new Scanner(new BufferedInputStream(System.in));
        writer = new OutputStreamWriter(System.out);  
        int n;
        int MAXN = 41;
        int fib[] = new int[MAXN];
        int sum[] = new int[MAXN];
        int ans[] = new int[MAXN];

        sum[0]=fib[0]=0;
        fib[1]=fib[2]=1;
        int m=38;
        for(int i=3;i<=m;i++) {
             fib[i]=fib[i-1]+fib[i-2];
        }
        for(int i=1;i<=m;i++) sum[i]=sum[i-1]+fib[i];
        int T=cin.nextInt();
        for(int kcase=1;kcase<=T;kcase++)
        {
            n = cin.nextInt();
            for(int i=1;i<=m;i++) ans[i]=0;
            for(int i=m;i>0;i--) {
                if (sum[i-1]<n&&n<=sum[i]) {
                    ans[i]=1;
                    n=n-sum[i-1]-1; 
                }
            }
            int p=m;
            while (0 == ans[p]) --p;
            try {
                for(;p>0;p--) writer.write(ans[p]+"");  
                writer.write("\n");
                writer.flush();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

UVA 12075 Counting Triangles

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[i]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
ll C(ll n) {
    return n*(n-1)*(n-2)/6;
}
ll gcd(ll a,ll b){if (!b) return a;return gcd(b,a%b);}
#define MAXN (1001)
ll f[MAXN][MAXN]={0};
int main()
{
//  freopen("uva12075.in","r",stdin);
//  freopen(".out","w",stdout);


    int m,n;
    int kcase=0;
    while(cin>>m>>n && m && n ) {
        ll ans=C((m+1)*(n+1))-C(m+1)*(n+1)-C(n+1)*(m+1);
        For(i,m) For(j,n) {
            ans -= 2LL*(m+1-i)*(n+1-j)*(gcd(i,j)-1);
        }   
        Pr(++kcase,ans)
    }


    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值