1. 程式人生 > >【蒻爆了的NOIP系列--普及組複賽】(6)NOIP2015普及組複賽題解

【蒻爆了的NOIP系列--普及組複賽】(6)NOIP2015普及組複賽題解

這只是一個作業,如果有幫到您的,我只能說。。。這不科學。。。
————————————華麗的分割線————————————
第一題:
第一題題目-第1頁
這題很水雙重for列舉直n次輸出當然你要數論我也沒辦法
程式碼:

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <queue>
#include <map> #define ci const int #define ri register int #define ll long long #define reg register #define boom return #define cmax(a,b) (a)>(b)?(a):(b) #define cmin(a,b) (a)<(b)?(a):(b) #define For(i,a,b) for(i=a;i<b;i++) using namespace std; int main() { int k,day,ans=0,count=0
,i=0; cin>>k; for(day=1;day<=k;day++) { if(i==count) { count++; i=0; } i++; ans+=count; } cout<<ans; return 0; } //沒有什麼是兩個巴掌不能解決的,如果有就再來兩個巴掌

————————————華麗的分割線————————————
第二題:
第二題題目-第1頁
也很水列舉每個?的周圍然後輸出這裡是程式碼:

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <queue>
#include <map>
#define ci const int
#define ri register int
#define ll long long
#define reg register
#define boom return 
#define cmax(a,b) (a)>(b)?(a):(b)
#define cmin(a,b) (a)<(b)?(a):(b)
#define For(i,a,b) for(i=a;i<b;i++)
using namespace std;

char a[100][100]={0},b[100][100]={0},AC;
int n,m;
int find(int x,int y)
{
    if(x>=0&&y>=0&&x<n&&y<m&&a[x][y]=='*')return 1;
    return 0;
}
int main()
{
    int i,j;
    cin>>n>>m;
    for(i=0;i<n;i++)for(j=0;j<m;j++)cin>>a[i][j];
    for(i=0;i<n;i++)
        for(j=0;j<m;j++)
            if(a[i][j]=='?')b[i][j]='0'+find(i-1,j-1)+find(i-1,j)+find(i-1,j+1)+find(i,j-1)+find(i,j+1)+find(i+1,j-1)+find(i+1,j)+find(i+1,j+1);
            else b[i][j]=a[i][j];
    for(i=0;i<n;i++)
    {
        for(j=0;j<m;j++)cout<<b[i][j];
        cout<<endl;
    }
    return 0;
}
//沒有什麼是兩個巴掌不能解決的,如果有就再來兩個巴掌 

話說 為什麼每年都要來一個遊戲啊(什麼時候出MC是個問題)
————————————華麗的分割線————————————
第三題:
第三題題目-第1頁
第三題題目-第2頁
首先你會發現y沒任何用只是確定x,z奇偶性相同。。。
然後貌似要用數論什麼乘法分配律來搞
一頭霧水(我才剛初一數學很弱)
所以把推理打出來不解釋
答案等於a1*(num a1*(n-1)+num a2+ num a3+……+num an)+ a2*(num a2*(n-1)+num a1+ num a3+……+num an)+……+an*(num a1*+num a2+ num a3+……+num an*(n-1))
用sum來表示num從a1到an的和,用sum2表示a1到an的和,答案=sum*sum2+(n-2)*sum2
不過%10007什麼的很噁心qwq
程式碼(全是被模搞長的!!!):

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <queue>
#include <map>
#include <climits>
#define ci const int
#define ri register int
#define ll long long
#define reg register
#define boom return 
#define cmax(a,b) (a)>(b)?(a):(b)
#define cmin(a,b) (a)<(b)?(a):(b)
#define For(i,a,b) for(i=a;i<b;i++)
using namespace std;

ci MAXN=100086,MOD=10007;
int sum[2][MAXN],color[MAXN],d[2][MAXN],nu[MAXN],n,m,ans;
int main()
{
    int i;

    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)scanf("%d",&nu[i]),nu[i]%=MOD;
    for(i=1;i<=n;i++)
    {
        scanf("%d",&color[i]),sum[i%2][color[i]]+=nu[i];
        sum[i%2][color[i]]%=MOD,d[i%2][color[i]]++;
    }
    for(i=1;i<=n;i++)
    {
        int tot;
        tot=d[i%2][color[i]]-2;
        tot=(sum[i%2][color[i]]+tot%MOD*nu[i]+MOD)%MOD;
        ans=(ans+i%MOD*tot)%MOD;
    }
    cout<<ans<<endl;
    return 0;
}
//沒有什麼是兩個巴掌不能解決的,如果有就再來兩個巴掌

————————————華麗的分割線————————————
第四題:
第四題題目-第1頁
第四題題目-第2頁
這道題因該是數結qwq
首先為了讓答案最大我們把每個家都記一個分值=路程*2+推銷的疲勞值
然後每次推銷加上這個值就好了。
不過每次操作後每家的路程對答案的貢獻都會減小(為什麼你知道的)
不過也不能全部都減我們記一個max為選了要去推銷的家的最遠路程。
比這個路程多的要全減少的清零。
所以我們開兩個優先佇列:

struct fam
{
    int s,poi,nu;
    bool operator<(fam b)const
    {
        if(poi!=b.poi)return poi<b.poi;//重定義小於號為了排序和優先順序qwq
        return s<b.s;
    }
};
priority_queue <fam> L,R;

然後每次把兩個佇列最大的數分別拿出來對比小的放回去
然後更新max以max為界重新更新兩個佇列
就完了qwq下面程式碼:

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <queue>
#include <map>
#include <climits>
#define ci const int
#define ri register int
#define ll long long
#define reg register
#define boom return 
#define cmax(a,b) (a)>(b)?(a):(b)
#define cmin(a,b) (a)<(b)?(a):(b)
#define For(i,a,b) for(i=a;i<b;i++)
char bbb[1<<15],*ss=bbb,*t=bbb;
#define getc()(ss==t&&(t=(ss=bbb)+fread(bbb,1,1<<15,stdin),ss==t)?0:*ss++)
using namespace std;
inline int scan() 
{
    register bool bb;register char ch;register int aa;
    while(ch=getc(),(ch<'0'||ch>'9')&&ch!='-');
    ch=='-'?(bb=1,aa=0):(bb=0,aa=ch-'0');
    while(ch=getc(),ch>='0'&&ch<='9') aa=(aa<<1)+(aa<<3)+ch-'0';
    bb?aa=-aa:0;
    return aa;
}
ci MAXN=1000086;
int n,vis[MAXN],ans,s[MAXN],a[MAXN],now;
struct fam
{
    int s,poi,nu;
    bool operator<(fam b)const
    {
        if(poi!=b.poi)return poi<b.poi;
        return s<b.s;
    }
};
priority_queue <fam> L,R;
fam MAX(fam a,fam b){return a<b?b:a;}
int main()
{
    ri i,j;

    n=scan();
    for(i=1;i<=n;i++)s[i]=scan();
    for(i=1;i<=n;i++)a[i]=scan(),R.push((fam){s[i],a[i]+s[i]*2,i});
    for(i=1;i<=n;i++)
    {
        fam x=(fam){0,0,0},y=(fam){0,0,0};
        if(R.size())
        {
            x=R.top();R.pop();
            while(x.s<=now && R.size())x=R.top(),R.pop();
            x.poi-=2*now;
        }
        if(L.size())y=L.top(),L.pop();
        fam big=MAX(x,y);
        if(big.nu==y.nu && x.nu)x.poi+=2*now,R.push(x);
        else if(big.nu==x.nu)L.push(y);
        printf("%d\n",ans+=big.poi),vis[big.nu]=1;
        if(big.s>now)
            for(now=big.s,j=1;j<=big.nu;j++)
                if(!vis[j])L.push((fam){s[j],a[j],j});
    }
    return 0;
}
//沒有什麼是兩個巴掌不能解決的,如果有就再來兩個巴掌

數結好題。
————————————華麗的分割線————————————
2015好水!!!!