题意:在1..n中取三个不同的整数,使其恰能构成3角形三边长,求取法数
枚举最大的边x,假设其中一条边为y,另一条边的取值范围是 (x−y,x) ,共y-1个解,总数为 (x−1)(x−2)/2
去掉y=z的三角形 x−1−x/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;
}
题意:在一个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;
}
题意:给一个树的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;
}
题意:已知正整数a,b,k,求有多少整数n满足 a≤n≤b,k|n,k|(n的数位和)
1≤a,b≤232,1≤k<10000
数位dp,注意 k≥100 的时候答案必为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;
}
题意:对于一个边平行于坐标轴的多边形,我们可以用一个由R和O组成的序列来描述它:从某个顶点开始按照逆时针顺序走,碰到一个90°的内角记R;碰到一个270°的内角记O。这样的序列称为角度序列。定义星型多边形为多边形中存在一个点可以看到多边形边界上每一个点。现在给定正整数n,求有多少个长度为L的角度序列至少可以对应一个星型多边形。其中多边形的每条边长任意。
本题等价于:长度为L的序列,要求序列中只有O和R,且R比O多4个,且头尾不能同位O,且不能有连续2个O出现,问符合条件的序列数
考虑R有4个,OR有p-4个,其排成的不同序列的个数为 C4p
再考虑 R…O 的序列数,刚好是 O…R 的序列数 C4p−1
注意奇数和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;
}
题意:有一个n条边的串并联网络,
2个串并联网络,串的顺序调换,并的顺序调换,视为相同
问满足题意的网络有几个?
1≤n≤30
考虑树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;
}
题意:求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;
}
题意:给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;
}
题意: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;
}
题意:在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;
}
题意:给n个点,无三点共线,随机取3个点构成一个三角形,问其中包含的点的个数的期望。
题意:给n个点,无三点共线,问构成的直角和锐角三角形的个数。
n≤1200
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;
}
题意:1~n的排列 (a1,…,an) ,恰有k个位置 ai>i ,已知 n ,求方案数
n≤1000
dp题,首先很容易想出递推式
f(n,k)=(k+1)∗f(n−1,k)+(n−k)∗f(n−1,k−1)
打表发现
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;
}
题意:求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;
}
题意:平面上有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;
}
有一条折线,起点(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)));
}
}
}
2进制中没有连续1的正整数,第 2<k<9∗107 大是多少?
找规律,发现长度为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();
}
}
}
}