NOIP2015 pj
达成成就!——尝试不看题解的情况下用cpp打完了一套NOIP pj
题目全部在luogu上——
P2669 金币
题目描述
国王将金币作为工资,发放给忠诚的骑士。第一天,骑士收到一枚金币;之后两天(第二天和第三天),每天收到两枚金币;之后三天(第四、五、六天),每天收到三枚金币;之后四天(第七、八、九、十天),每天收到四枚金币……;这种工资发放模式会一直这样延续下去:当连续N天每天收到N枚金币后,骑士会在之后的连续N+1天里,每天收到N+1枚金币。
请计算在前K天里,骑士一共获得了多少金币。
输入输出格式
输入格式:输入文件只有1行,包含一个正整数K,表示发放金币的天数。
输出格式:输出文件只有1行,包含一个正整数,即骑士收到的金币数。
输入输出样例
6
14
1000
29820
说明
【输入输出样例 1 说明】
骑士第一天收到一枚金币;第二天和第三天,每天收到两枚金币;第四、五、六天,
每天收到三枚金币。因此一共收到 1+2+2+3+3+3=14 枚金币。
对于 100%的数据, 1 ≤ K ≤ 10,000。
Solution
直接模拟
1 #include<cstdio> 2 using namespace std; 3 4 int main(){ 5 //freopen("1.in","r",stdin); 6 //freopen("1.out","w",stdout); 7 8 int n; 9 int i=0; 10 int ans=0; 11 12 scanf("%d",&n); 13 14 while (n>0) 15 { 16 n-=++i; 17 ans=ans+i*i; 18 } 19 20 ans=ans-(0-n)*i; 21 printf("%d",ans); 22 23 fclose(stdin); fclose(stdout); 24 return 0; 25 }
P2670 扫雷游戏
题目描述
扫雷游戏是一款十分经典的单机小游戏。在n行m列的雷区中有一些格子含有地雷(称之为地雷格),其他格子不含地雷(称之为非地雷格)。玩家翻开一个非地雷格时,该格将会出现一个数字——提示周围格子中有多少个是地雷格。游戏的目标是在不翻出任何地雷格的条件下,找出所有的非地雷格。
现在给出n行m列的雷区中的地雷分布,要求计算出每个非地雷格周围的地雷格数。
注:一个格子的周围格子包括其上、下、左、右、左上、右上、左下、右下八个方向上与之直接相邻的格子。
输入输出格式
输入格式:输入文件第一行是用一个空格隔开的两个整数n和m,分别表示雷区的行数和列数。
接下来n行,每行m个字符,描述了雷区中的地雷分布情况。字符’*’表示相应格子是地雷格,字符’?’表示相应格子是非地雷格。相邻字符之间无分隔符。
输出格式:输出文件包含n行,每行m个字符,描述整个雷区。用’*’表示地雷格,用周围的地雷个数表示非地雷格。相邻字符之间无分隔符。
输入输出样例
3 3 *?? ??? ?*?
*10 221 1*1
2 3 ?*? *??
2*1 *21
说明
对于 100%的数据, 1≤n≤100, 1≤m≤100。
Solution
还是模拟。。。
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 int main(){ 5 char c[100][100]; 6 int apple[102][102]; 7 memset(apple,0,sizeof(apple)); 8 freopen("1.in","r",stdin); 9 freopen("1.out","w",stdout); 10 11 int n,m; 12 scanf("%d %d\n",&n,&m); 13 14 for (int i=1;i<=n;i++){ 15 for (int j=1;j<=m;j++) 16 { 17 scanf("%c",&c[i][j]); 18 if (c[i][j]=='*'){ 19 apple[i-1][j-1]++; 20 apple[i+1][j+1]++; 21 apple[i][j-1]++; 22 apple[i-1][j]++; 23 apple[i][j+1]++; 24 apple[i+1][j]++; 25 apple[i-1][j+1]++; 26 apple[i+1][j-1]++; 27 } 28 } 29 scanf("\n"); 30 } 31 for (int i=1;i<=n;i++) 32 { 33 for (int j=1; j<=m;j++){ 34 if (c[i][j]=='?') printf("%d",apple[i][j]); 35 else printf("*"); 36 } 37 printf("\n"); 38 } 39 40 }
P2671 求和
题目描述
一条狭长的纸带被均匀划分出了n个格子,格子编号从1到n。每个格子上都染了一种颜色color_i用[1,m]当中的一个整数表示),并且写了一个数字number_i。
定义一种特殊的三元组:(x,y,z),其中x,y,z都代表纸带上格子的编号,这里的三元
组要求满足以下两个条件:
1.xyz是整数,x<y<z,y-x=z-y
2.colorx=colorz
满足上述条件的三元组的分数规定为(x+z)*(number_x+number_z。整个纸带的分数
规定为所有满足条件的三元组的分数的和。这个分数可能会很大,你只要输出整个纸带的分数除以10,007所得的余数即可。
输入输出格式
输入格式:第一行是用一个空格隔开的两个正整数n和m,n表纸带上格子的个数,m表纸带上颜色的种类数。
第二行有n用空格隔开的正整数,第i数字number表纸带上编号为i格子上面写的数字。
第三行有n用空格隔开的正整数,第i数字color表纸带上编号为i格子染的颜色。
输出格式:共一行,一个整数,表示所求的纸带分数除以10,007所得的余数。
输入输出样例
6 2 5 5 3 2 2 2 2 2 1 1 2 1
82
15 4 5 10 8 2 2 2 9 9 7 7 5 6 4 2 4 2 2 3 3 4 3 3 2 4 4 4 4 1 1 1
1388
说明
【输入输出样例 1 说明】
纸带如题目描述中的图所示。
所有满足条件的三元组为: (1, 3, 5), (4, 5, 6)。
所以纸带的分数为(1 + 5)*(5 + 2) + (4 + 6)*(2 + 2) = 42 + 40 = 82。
对于第 1 组至第 2 组数据, 1 ≤ n ≤ 100, 1 ≤ m ≤ 5;
对于第 3 组至第 4 组数据, 1 ≤ n ≤ 3000, 1 ≤ m ≤ 100;
对于第 5 组至第 6 组数据, 1 ≤ n ≤ 100000, 1 ≤ m ≤ 100000,且不存在出现次数
超过 20 的颜色;
对 于 全 部 10 组 数 据 , 1 ≤ n ≤ 100000, 1 ≤ m ≤ 100000, 1 ≤ color_i ≤ m,1≤number_i≤100000
Solution
先按颜色排序,把同颜色的归为一类,然后根据奇偶性瞎搞就可以了,取模打错了好多次。。。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 long long n,m; 7 long long color[100001],num[100001],id[100001]; 8 const long long moding=10007; 9 10 void swap(long long &aa,long long &bb){ //swap function 11 long long tt; 12 tt=aa; 13 aa=bb; 14 bb=tt; 15 } 16 17 void qsort(long long l,long long r){ 18 long long i=l,j=r,mi=id[(l+r)/2]; 19 long long mm=color[(l+r)/2]; 20 21 do 22 { 23 while ((color[i]<mm)||(color[i]==mm&&id[i]<mi)) i++; 24 while ((color[j]>mm)||(color[j]==mm&&mi<id[j])) j--; //double keys qsort 25 if (i<=j){ 26 swap(color[i],color[j]); 27 swap(num[i],num[j]); 28 swap(id[i],id[j]); 29 i++;j--; 30 } 31 }while (i<=j); 32 33 if (l<j) qsort(l,j); 34 if (i<r) qsort(i,r); 35 } 36 37 int partit(long long l,long long r){ 38 // long long odd_num[100001],no_num[100001]; 39 // long long odd_color[100001],no_color[100001]; 40 long long odd=0,no=0,odd_sum=0,no_sum=0,tmp=0; 41 42 for (long long j=l;j<=r;j++) 43 if (id[j]%2==1) { 44 odd++; 45 odd_sum+=id[j]; 46 // odd_num[odd]=num[j]; odd_color[odd]=color[j]; 47 } 48 else { 49 no++; 50 no_sum+=id[j]; 51 // no_num[no]=num[j]; no_color[no]=color[j]; 52 } 53 for (long long j=l;j<=r;j++) 54 if (id[j]%2==1) { 55 if (odd>1) tmp=((tmp % moding)+(num[j]*(odd_sum+id[j]*(odd-2)))%moding)%moding; 56 // printf("%lld \n",tmp); printf("----\n"); 57 } 58 else if (no>1) tmp=((tmp % moding)+(num[j]*(no_sum+id[j]*(no-2)))%moding)%moding; 59 // printf("%lld \n",tmp); printf("======\n"); 60 return tmp % moding; 61 } 62 int main(){ 63 long long ll=1,ans=0; 64 65 freopen("sum.in","r",stdin); 66 freopen("sum.out","w",stdout); 67 68 scanf("%lld %lld\n",&n,&m); 69 for (long long i=1;i<=n;i++) scanf("%lld ",&num[i]); 70 for (long long i=1;i<=n;i++) scanf("%lld ",&color[i]); 71 for (long long i=1;i<=n;i++) id[i]=i; 72 73 qsort(1,n); 74 75 for (long long i=2;i<=n+1;i++) 76 if (color[i]!=color[i-1]) 77 { 78 ans=((ans % moding)+partit(ll,i-1))%moding; 79 ll=i; 80 } 81 printf("%lld",ans); 82 return 0; 83 }
P2672 推销员
题目描述
阿明是一名推销员,他奉命到螺丝街推销他们公司的产品。螺丝街是一条死胡同,出口与入口是同一个,街道的一侧是围墙,另一侧是住户。螺丝街一共有N家住户,第i家住户到入口的距离为Si米。由于同一栋房子里可以有多家住户,所以可能有多家住户与入口的距离相等。阿明会从入口进入,依次向螺丝街的X家住户推销产品,然后再原路走出去。
阿明每走1米就会积累1点疲劳值,向第i家住户推销产品会积累Ai点疲劳值。阿明是工作狂,他想知道,对于不同的X,在不走多余的路的前提下,他最多可以积累多少点疲劳值。
输入输出格式
输入格式:第一行有一个正整数N,表示螺丝街住户的数量。
接下来的一行有N个正整数,其中第i个整数Si表示第i家住户到入口的距离。数据保证S1≤S2≤…≤Sn<10^8。
接下来的一行有N个正整数,其中第i个整数Ai表示向第i户住户推销产品会积累的疲劳值。数据保证Ai<10^3。
输出格式:输出N行,每行一个正整数,第i行整数表示当X=i时,阿明最多积累的疲劳值。
输入输出样例
5 1 2 3 4 5 1 2 3 4 5
15 19 22 24 25
5 1 2 2 4 5 5 4 3 4 1
12 17 21 24 27
说明
【输入输出样例1说明】
X=1:向住户5推销,往返走路的疲劳值为5+5,推销的疲劳值为5,总疲劳值为15。
X=2:向住户4、5推销,往返走路的疲劳值为5+5,推销的疲劳值为4+5,总疲劳值为5+5+4+5=19。
X=3:向住户3、4、5推销,往返走路的疲劳值为5+5,推销的疲劳值3+4+5,总疲劳值为5+5+3+4+5=22。
X=4:向住户2、3、4、5推销,往返走路的疲劳值为5+5,推销的疲劳值2+3+4+5,总疲劳值5+5+2+3+4+5=24。
X=5:向住户1、2、3、4、5推销,往返走路的疲劳值为5+5,推销的疲劳值1+2+3+4+5,总疲劳值5+5+1+2+3+4+5=25。
【输入输出样例2说明】
X=1:向住户4推销,往返走路的疲劳值为4+4,推销的疲劳值为4,总疲劳值4+4+4=12。
X=2:向住户1、4推销,往返走路的疲劳值为4+4,推销的疲劳值为5+4,总疲劳值4+4+5+4=17。
X=3:向住户1、2、4推销,往返走路的疲劳值为4+4,推销的疲劳值为5+4+4,总疲劳值4+4+5+4+4=21。
X=4:向住户1、2、3、4推销,往返走路的疲劳值为4+4,推销的疲劳值为5+4+3+4,总疲劳值4+4+5+4+3+4=24。或者向住户1、2、4、5推销,往返走路的疲劳值为5+5,推销的疲劳值为5+4+4+1,总疲劳值5+5+5+4+4+1=24。
X=5:向住户1、2、3、4、5推销,往返走路的疲劳值为5+5,推销的疲劳值为5+4+3+4+1,
总疲劳值5+5+5+4+3+4+1=27。
【数据说明】
对于20%的数据,1≤N≤20;
对于40%的数据,1≤N≤100;
对于60%的数据,1≤N≤1000;
对于100%的数据,1≤N≤100000。
Solution
刚开始测了一下二维的暴力只拿了40;
于是开始各种奇怪的东西,=>
首先我们可以发现在找x个买家时,我们可以从x-1的推过来,于是很明显的阶段性,决策有已经走了的和后面的,这里来个堆维护最大值就可以了,
但是我作死维护了两棵线段树。。。。。
然后还学会了gdb。。。。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define ll long long 5 #define pr(a) for(long long i=1;i<=n;i++) printf("%lld ",a[i]);printf("\n"); 6 const ll maxn=100000+2; 7 using namespace std; 8 9 10 typedef struct { 11 ll val,left,right; 12 }arr; 13 14 //define var ===================== 15 16 ll n,ap; 17 arr tree[4*maxn-1],tree2[4*maxn-1]; 18 ll dis[maxn],tir[maxn],diss[maxn]; 19 bool check[maxn]; 20 21 //main codes ===================== 22 23 void swap(long long &aa,long long &bb){ //swap function 24 long long tt; 25 tt=aa; 26 aa=bb; 27 bb=tt; 28 } 29 30 void qsort(long long l,long long r){ 31 long long i=l,j=r; 32 long long mm=dis[(l+r)/2]; 33 34 do 35 { 36 while (dis[i]<mm) i++; 37 while (dis[j]>mm) j--; //double keys qsort 38 if (i<=j){ 39 swap(dis[i],dis[j]); 40 swap(tir[i],tir[j]); 41 i++;j--; 42 } 43 }while (i<=j); 44 45 if (l<j) qsort(l,j); 46 if (i<r) qsort(i,r); 47 } 48 49 50 void init(){ 51 //freopen("1.in","r",stdin); 52 // freopen("1.out","w",stdout); 53 54 memset(check,1,sizeof(check)); 55 scanf("%lld",&n); 56 57 for (ll i=1;i<=n;i++) scanf("%lld ",&dis[i]); 58 for (ll i=1;i<=n;i++) scanf("%lld ",&tir[i]); 59 60 tir[0]=0; dis[0]=0; 61 qsort(1,n); 62 } 63 64 void build( ll l , ll r , ll w){ 65 66 tree[w].left=l; tree[w].right=r; 67 ll mid=(l+r)/2; 68 69 if (l==r) { 70 tree[w].val=l; 71 return; 72 } 73 74 build(l,mid,2*w); 75 76 build(mid+1,r,2*w+1); 77 78 if (dis[tree[2*w].val]>dis[tree[2*w+1].val]) 79 tree[w].val= tree[2*w].val; 80 else 81 tree[w].val= tree[2*w+1].val; 82 83 } 84 85 ll query( ll l , ll r , ll w){ 86 87 if (l<=tree[w].left&&tree[w].right<=r) return tree[w].val; 88 89 ll t1=0,t2=0; 90 91 if (l<=tree[2*w].right) t1=query(l,r,2*w); 92 if (tree[2*w+1].left<=r) t2=query(l,r,2*w+1); 93 if (dis[t1]>dis[t2]) return t1; 94 if (dis[t1]==dis[t2]) return min(t1,t2); 95 else return t2; 96 } 97 98 99 100 void build2( ll l , ll r , ll w){ 101 102 tree2[w].left=l; tree2[w].right=r; 103 ll mid=(l+r)/2; 104 105 if (l==r) { 106 tree2[w].val=l; 107 return; 108 } 109 110 build2(l,mid,2*w); 111 112 build2(mid+1,r,2*w+1); 113 114 if (tir[tree2[2*w].val]>tir[tree2[2*w+1].val]) 115 tree2[w].val= tree2[2*w].val; 116 else 117 tree2[w].val= tree2[2*w+1].val; 118 119 } 120 121 ll query2( ll l , ll r , ll w){ 122 123 if (l<=tree2[w].left&&tree2[w].right<=r) return tree2[w].val; 124 125 ll t1=0,t2=0; 126 127 if (l<=tree2[2*w].right) t1=query2(l,r,2*w); 128 if (tree2[2*w+1].left<=r) t2=query2(l,r,2*w+1); 129 130 if (tir[t1]>tir[t2]) return t1; 131 if (tir[t1]==tir[t2]) return min(t1,t2); 132 else return t2; 133 } 134 135 void update2( ll x, ll w){ 136 137 if (x==tree2[w].left&&x==tree2[w].right) { 138 tree2[w].val=0; 139 return; 140 } 141 if (x<=tree2[2*w].right) update2(x,2*w); 142 else update2(x,2*w+1); 143 144 if (tir[tree2[2*w].val]>tir[tree2[2*w+1].val]) 145 tree2[w].val= tree2[2*w].val; 146 else 147 tree2[w].val= tree2[2*w+1].val; 148 } 149 void update( ll x, ll w){ 150 151 if (x==tree[w].left&&x==tree[w].right) { 152 tree[w].val=0; 153 return; 154 } 155 if (x<=tree[2*w].right) update(x,2*w); 156 else update(x,2*w+1); 157 158 if (dis[tree[2*w].val]>dis[tree[2*w+1].val]) 159 tree[w].val= tree[2*w].val; 160 else 161 tree[w].val= tree[2*w+1].val; 162 } 163 164 int main(){ 165 166 init(); 167 168 memcpy(diss,dis,sizeof(dis)); 169 for (ll i=1;i<=n;i++) 170 dis[i]=dis[i]*2+tir[i]; 171 build(1,n,1); 172 build2(1,n,1); 173 174 ll last=query(1,n,1),php1,php2; 175 ll ans=dis[last]; 176 update(last,1); 177 update2(last,1); 178 // printf("last=%lld ans=%lld\n",last,ans); 179 printf("%lld\n",ans); 180 for (ll i=2;i<=n;i++) 181 { 182 ap=i; 183 php1=query2(1,last-1,1); 184 if (last+1<=n)php2=query(last+1,n,1); else php2=0; 185 // printf("%lld %lld \n",dis[php2],last); 186 if (tir[php1]>dis[php2]-diss[last]*2) { 187 ans+=tir[php1]; 188 update2(php1,1);update(php1,1); 189 } 190 else { 191 ans+=dis[php2]-diss[last]*2; 192 last=php2; 193 update(php2,1); 194 update2(php2,1); 195 } 196 // printf("last=%lld ans=%lld\n",last,ans); 197 printf("%lld\n",ans); 198 } 199 // printf("%lld \n",tir[0]); 200 return 0; 201 202 }