【用膝蓋寫程式碼系列】(5):NOIP2013普及組複賽詳解
阿新 • • 發佈:2019-01-30
有人問我為什麼2013在2014之後?
那是因為。。。。。。你醜(這句劃掉)
2013年難啊!
……
第一題:計數問題
題面簡述:試計算在區間 1 到 n 的所有整數中,數字 x(0 ≤ x ≤ 9)共出現了多少次?
陷阱提示:這道題和之前的數字統計有異曲同工之妙~
資料範圍:對於 100%的資料,
思路描述:這道題需要換一點做法。不斷地對數i取餘10,直到該數小於10為止。這樣可以去除i的每一位。
我的程式碼:
#include <cstdio>
int main(){
int i,j,n,m,x;
int l,r,count=0 ;
scanf("%d%d",&n,&x);
long num = 0;
for(i=1;i<=n;i++){
j = i;
while(j>0){
if(j%10==x) num++;
j/=10;
}
}
printf("%d",num);
}
第一題完。
第二題:表示式求值
題意簡述:給定一個只包含加法和乘法的算術表示式,請你程式設計計算表示式的值。
陷阱提示:注意 優先順序!
資料範圍:0≤表示式中加法運算子和乘法運算子的總數≤100000。
思路描述:這裡講究的是輸入。這裡要一邊輸入一遍判斷。如果當前輸入的是符號,那麼開始計算即可。
我的程式碼:
/*
作者:xiaoyao24256
題目:p3292 表示式求值
*/
#include <iostream>
#include <cstdio>
using namespace std;
int main(){
long long int a,sum=0,tot = 0;
int i,j,k,n,m;
char c;
scanf("%lld",&sum);
sum%=10000;
while (scanf("%c",&c)!=EOF&&(c=='*'||c=='+'))
{
scanf("%lld",&a);
a%=10000;
// cout<<"a= "<<a<<endl;
if(c == '*'){
sum=(sum*a)%10000;
}
// cout<<"sum="<<sum<<" tot="<<tot<<" a="<<a<<endl;
if(c=='+'){
tot=(tot+sum)%10000;
sum=a;
}
}
tot+=sum;
tot%=10000;
cout<<tot;
}
第二題完。
第三題:小朋友的數字
題意簡述:給定一個長n的數列,每個數字有一個特徵值,為它之前的最大欄位和,每個數字有一個分數,為它前面數字的特徵值加上它本身的特徵值。求出這個數列中最大的一個分數。
陷阱提示:這裡不能忽略負數。
資料範圍:
思路描述:這道題其實也十分簡單。用最大欄位和求一下特徵值,然後設數1的分數為它本身,就可以完美解決這一道題目。這道題的答案有可能在兩個地方:第一個數字和最後一個數字。如果在後面的序列中有任何一個數比第一個數大,就輸出最後一個數,否則輸出第一個數(的分數)
我的程式碼:
#include<iostream>
#include<cstdio>
#define MAXN 1000001
using namespace std;
bool flag;
long long n,m,f[MAXN],a[MAXN],tot,g[MAXN],w[MAXN];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
f[1]=a[1];
long long maxx=a[1];
w[1]=a[1];
for(int i=2;i<=n;i++)
{
f[i]=max(f[i-1]+a[i],a[i]);
w[i]=max(w[i-1],f[i]);
}
g[1]=w[1];
g[2]=w[1]+g[1];
if(g[2]>=g[1])
flag=1;
for(int i=3;i<=n;i++){
if(w[i-1]>0){
g[i]=(w[i-1]+g[i-1])%m;
if(g[i]>g[1]) flag=1;
}
else g[i]=g[2];
}
if(flag)
printf("%d",g[n]);
else
printf("%d",g[1]%m);
return 0;
}
第三題,猝。
抱歉,第四題我實在無能為力。
對不起。