NOIP模拟题 [模拟][递推][平衡规划]

5 篇文章 0 订阅
5 篇文章 0 订阅

在写暴力的时候也不要放过发现的每一个题目特点,这可能就是正解的关键。

T1:
题意:
求给定一个序列最大公约数为1的最长长度;
分析:
傻逼题,害我读了几次题。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<ctime>
#define ll long long 
#define inf 2e8
#define clr(x) memset(x,0,sizeof(x))
#define maxen(x) memset(x,127,sizeof(x))
#define maxer(x) memset(x,31,sizeof(x))
#define minus(x) memset(x,-1,sizeof(x))
#define each(i,n,m) for(int i=n;i<m;i++)
#define eachrev(i,n,m) for(int i=n;i>m;i--)
#define minn(a,b,c) min(a,min(b,c))
#define maxx(a,b,c) max(a,max(b,c))
#ifdef WIN32
#define lld "%I64d"
#else
#define lld "%lld"
#endif
#define PROC "seq"
//for(int i=1;i<=n;i++)
//(double) (ll) LL (int)
//(double)clock()/CLOCKS_PER_SEC
using namespace std;
const int modd=1e9+7;
ll n,s;
ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
ll gcd(ll a,ll b)
{
    return (b==0?a:gcd(b,a%b));
}
void init()
{
    n=read();
    s=read();
    for(int i=2;i<=n;i++)
        s=gcd(s,read());
}
void work()
{
    if(s!=1)printf("-1");
    else printf(lld,n);
}
void debug()
{
    //
}
int main()
{
    freopen(PROC".in","r",stdin);
    freopen(PROC".out","w",stdout);
    init();
    work();
    //debug();
    return 0;
}

T2:
题意:
给定矩阵大小n*m,要求每个n*n矩阵都有k小矩形被涂色的方案总数。
分析:
画一画就会发现,前n列确定以后就确定了方案,接下来乘就行了。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<ctime>
#define ll long long 
#define inf 2e8
#define clr(x) memset(x,0,sizeof(x))
#define maxen(x) memset(x,127,sizeof(x))
#define maxer(x) memset(x,31,sizeof(x))
#define minus(x) memset(x,-1,sizeof(x))
#define each(i,n,m) for(ll i=n;i<m;i++)
#define eachrev(i,n,m) for(ll i=n;i>m;i--)
#define minn(a,b,c) min(a,min(b,c))
#define maxx(a,b,c) max(a,max(b,c))
#ifdef WIN32
#define lld "%I64d"
#else
#define lld "%lld"
#endif
#define PROC "table"
//for(ll i=1;i<=n;i++)
//(double) (ll) LL (ll)
//(double)clock()/CLOCKS_PER_SEC
using namespace std;
const ll Maxn=105;
const ll modd=1e9+7;
ll n,m,k,f[Maxn][Maxn*Maxn],lim2;
ll ans,c[Maxn],ni[Maxn];
ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
ll jc(ll n)
{
    ll ret=1;
    for(ll i=1;i<=n;i++)
        (ret*=i)%=modd;
    return ret;
}
ll qm(ll a,ll b)
{
    ll ret=1;
    while(b){
        if(b&1)(ret*=a)%=modd;
        (a*=a)%=modd;
        b>>=1;
    }
    return ret;
}
void init()
{
    n=read();
    m=read();
    k=read();
    ll lim=jc(n);
    lim2=min(n,k);
    for(ll i=0;i<=lim2;i++)
        c[i]=lim*qm(jc(i),modd-2)%modd*qm(jc(n-i),modd-2)%modd;
}
void work()
{
    f[0][0]=1;
    for(int i=1;i<=n;i++){
    for(int j=0;j<=k;j++)
    ni[j]=qm(c[j],(m-(ll)i)/n+1LL);
    for(int j=0;j<=k;j++)
    for(int z=0;z<=j;z++)
    (f[j][i]+=f[z][i-1]*ni[j-z]%modd)%=modd;
    }
    printf(lld,f[k][n]);
}
void debug()
{
    //
}
int main()
{
    freopen(PROC".in","r",stdin);
    freopen(PROC".out","w",stdout);
    init();
    work();
    //debug();
    return 0;
}

T3:
题意:
给定n个点,求组成边与坐标轴平行的正方形的方案数。
分析:
有两个暴力方法,极端情况出现的条件不一样。
所以分一下类就可以了,据说叫平衡规划,高级。
hash才能不T,明天写吧orz。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<ctime>
#define ll long long 
#define inf 2e8
#define clr(x) memset(x,0,sizeof(x))
#define maxen(x) memset(x,127,sizeof(x))
#define maxer(x) memset(x,31,sizeof(x))
#define minus(x) memset(x,-1,sizeof(x))
#define each(i,n,m) for(int i=n;i<m;i++)
#define eachrev(i,n,m) for(int i=n;i>m;i--)
#define minn(a,b,c) min(a,min(b,c))
#define maxx(a,b,c) max(a,max(b,c))
#ifdef WIN32
#define lld "%I64d"
#else
#define lld "%lld"
#endif
#define PROC "square"
//for(int i=1;i<=n;i++)
//(double) (ll) LL (int)
//(double)clock()/CLOCKS_PER_SEC
using namespace std;
const int Maxn=100000+5;
const int modd=1e9+7;
int n,x[Maxn],y[Maxn],tot[Maxn],lll[Maxn];
ll ans;
vector<int>e1[Maxn],e2[Maxn];
un
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}
void init()
{
    n=read();
    for(int i=1;i<=n;i++){
        x[i]=read();y[i]=read();
        e1[x[i]].push_back(y[i]);
        e2[y[i]].push_back(x[i]);
    }
    for(int i=0;i<=100000;i++)sort(e1[i].begin(),e1[i].end());
    for(int i=0;i<=100000;i++)sort(e2[i].begin(),e2[i].end());
}
void work()
{
    int mmm=int(sqrt(n))+1;
    for(int i=0;i<=100000;i++)
    if(e1[i].size()&&e1[i].size()<mmm){
        vector<int>::iterator iii=e1[i].begin();
        vector<int>::iterator len1=e1[i].end();
        vector<int>::iterator x1;
        for(;iii+1<len1;iii++)
            for(x1=iii+1;x1<len1;x1++)
            {
            vector<int>::iterator tmp=lower_bound(e2[(*x1)].begin(),e2[(*x1)].end(),i+(*x1)-(*iii));
            vector<int>::iterator tmp2=lower_bound(e2[(*iii)].begin(),e2[(*iii)].end(),i+(*x1)-(*iii));
            if((*tmp)==i+(*x1)-(*iii)&&(*tmp2)==i+(*x1)-(*iii))
                ans+=1LL;
            if(i-(*x1)+(*iii)>=0&&lll[i-(*x1)+(*iii)]){
            vector<int>::iterator tmp=lower_bound(e2[(*x1)].begin(),e2[(*x1)].end(),i-(*x1)+(*iii));
            vector<int>::iterator tmp2=lower_bound(e2[(*iii)].begin(),e2[(*iii)].end(),i-(*x1)+(*iii));
            if((*tmp)==i-(*x1)+(*iii)&&(*tmp2)==i-(*x1)+(*iii))
            ans+=1LL;
            }
            }
    }
    else if(e1[i].size()){tot[++tot[0]]=i;lll[i]=1;}
    for(int z=1;z<tot[0];z++)
        for(int kk=z+1;kk<=tot[0];kk++){
        int i=tot[z];
        int j=tot[kk];
        vector<int>::iterator iii=e1[i].begin();
        vector<int>::iterator len1=e1[i].end();
        for(;iii<len1;iii++){
            vector<int>::iterator tmp=lower_bound(e1[i].begin(),e1[i].end(),(*iii)+i-j);
            vector<int>::iterator tmp2=lower_bound(e1[j].begin(),e1[j].end(),(*iii));
            if((*tmp)==(*iii)+i-j&&(*tmp2)==(*iii))
                ans+=1LL;
        }
        }
    printf(lld,ans);
}
void debug()
{
    //
}
int main()
{
    freopen(PROC".in","r",stdin);
    freopen(PROC".out","w",stdout);
    init();
    work();
    //debug();
    return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值