第一次很顺畅地AK呢,发篇题解纪念一下。
思路
直接扫一遍,如果该位上不是 0 0 0,那么它就一定是一个Round Number的首位。然后根据位值原理,后面填 0 0 0就可以啦。
如 5401 5401 5401中的 4 4 4代表的是 4 4 4个 100 100 100,那么一个Round Number就是 4 × 100 = 400 4×100=400 4×100=400。
代码
#include
#define int long long
using namespace std;
signed main()
{
int t;
cin>>t;
while (t--)
{
int pos=1,cnt=0,ans[10];
string s;
cin>>s;
for (int i=s.size()-1;i>=0;i--)
{
if (s[i]!='0') ans[++cnt]=(s[i]-'0')*pos;
pos*=10;
}
cout<<cnt<<endl;
for (int i=1;i<=cnt;i++) cout<<ans[i]<<' ';
cout<<endl;
}
return 0;
}
难度: 入门
思路
个人认为本题的正解与数论没个P关系。
直接看它能否拆成几个奇数或者几个偶数之和。我们定义两个数组 A , B A, B A,B, A A A尝试了奇数的拆分, B B B尝试了偶数的拆分。
那么,对于所有的 1 ≤ i ≤ n − 1 1≤i≤n-1 1≤i≤n−1的正整数 i i i,均将 A i A_i Ai赋为1, B i B_i Bi赋为2(注意输出的所有数必须都是正整数,所以 B i B_i Bi不能赋为0),然后算一算 A n A_n An与 B n B_n Bn就可以啦。
如果 A n > 0 A_n>0 An>0且 A n A_n An为奇数,那么就输出Yes与数组 A A A。
如果$ B n > 0 B_n>0 Bn>0且 B n B_n Bn为偶数,那么久输出Yes与数组 B B B。
如果发现前者与后者均不满足,那么就直接打印 N O NO NO。
代码
#include
#define int long long
using namespace std;
int t,n,k;
signed main()
{
cin>>t;
while (t--)
{
int a[105]={0},b[105]={0};
cin>>n>>k;
if (n<k)
{
cout<<"NO"<<endl;
continue;
}
for (int i=1;i<=k-1;i++) a[i]=1,b[i]=2;
a[k]=n-(k-1);
b[k]=n-2*(k-1);
if (a[k]%2==1&&a[k]>0)
{
cout<<"YES"<<endl;
for (int i=1;i<=k;i++) cout<<a[i]<<' ';
}
else if (b[k]%2==0&&b[k]>0)
{
cout<<"YES"<<endl;
for (int i=1;i<=k;i++) cout<<b[i]<<' ';
}
else cout<<"NO";
cout<<endl;
}
return 0;
}
难度: 普及-
怎么全是小学奥数题啊
首先在草稿纸上尝试找到规律。 1 , 2 , 3 … … n − 1 , n + 1 , n + 2 , n + 3 … … 2 n − 1 , 2 n + 1 … … 1,2,3……n-1,n+1,n+2,n+3……2n-1,2n+1…… 1,2,3……n−1,n+1,n+2,n+3……2n−1,2n+1……
规律显然,然后用周期问题搞一搞就可以啦。
#include
#define int long long
using namespace std;
int t,n,k;
signed main()
{
cin>>t;
while (t--)
{
int pos=0;
cin>>n>>k;//4 12
pos+=(k/(n-1))*n;//16
if (k%(n-1)==0) pos--;//找到上一个周期的末位
int now=k%(n-1);//加上剩下的一部分
if (now<n) pos+=now;
else pos+=(now+1);
cout<<pos<<endl;
}
return 0;
}
难度: 普及-
思路
按照题意模拟即可,但是有些考验代码能力与心态 (TM调试得累死了)
#include
#define int long long
using namespace std;
int t,n;
int a[200005];
signed main()
{
cin>>t;
while (t--)
{
cin>>n;
for (int i=1;i<=n;i++) cin>>a[i];
int head=0,tail=n+1,cnt=0,alice=0,bob=0,last=0;
while (head+1<tail)
{
cnt++;
if (cnt%2==1)
{
int sumv=0;
for (int i=head+1;i<tail;i++)
{
sumv+=a[i];
if (sumv>last)
{
head=i;
break;
}
}
alice+=sumv;
if (sumv<=last) break;
last=sumv;
}
else if (cnt%2==0)
{
int sumv=0;
for (int i=tail-1;i>head;i--)
{
sumv+=a[i];
if (sumv>last)
{
tail=i;
break;
}
}
bob+=sumv;
if (sumv<=last) break;
last=sumv;
}
}
cout<<cnt<<' '<<alice<<' '<<bob<<endl;
}
return 0;
}
难度: 普及-
思路
首先,看到 n ≤ 8000 n≤8000 n≤8000的限制与 1000 m s 1000ms 1000ms的限制,告诉我们正解应该是一个常数小的 O ( n 2 ) O(n^2) O(n2)算法。但是,空间限制只有 64 M B 64MB 64MB,说明我们必须摒弃大空间写法。
于是,我开始考虑,先用 O ( n 2 ) O(n^2) O(n2)的代价找到, 1 − n 1-n 1−n中的每个数是否能够成为一个长度不小于2的区间内各数之和。最后扫一遍,数一数这样的 S p e c i a l E l e m e n t s Special Elements SpecialElements即可。
但是怎么用仅仅 O ( n 2 ) O(n^2) O(n2)且小空间的方法来找到所有 S p e c i a l E l e m e n t s Special Elements SpecialElements的值呢?
首先,定义一个 v i s i t e d visited visited数组,其中 v i s i t e d i visited_i visitedi表示 i i i能否成为 S p e c i a l Special Special E l e m e n t Element Element的值。
①不需要大空间。虽然一个区间的和可能会达到 n 2 n^2 n2,但是所有的数均不大于 n n n,也就意味着所有 S p e c i a l Special Special E l e m e n t s Elements Elements的值均不大于 n n n。所以 v i s i t e d visited visited数组的大小开到 n n n就可以啦。
②我们枚举 l l l,然后找 r r r。用一个 s u m v sumv sumv来计算目前 Σ i = l r a i Σ_{i=l}^r a_i Σi=lrai的值,只要 s u m v sumv sumv超过了 n n n就立刻跳出( l → l + 1 l→l+1 l→l+1)。对于所有满足要求的 s u m v ( s u m v ≤ n ) sumv(sumv≤n) sumv(sumv≤n),将 v i s i t e d s u m v visited_{sumv} visitedsumv的值赋为1。
最后扫一遍,看看 v i s i t e d a i visited_{a_i} visitedai是否为1就知道它是否为 S p e c i a l E l m e n t Special Elment SpecialElment啦。数一数即可。
时间复杂度: O ( c 1 n 2 ) O(c_1n^2) O(c1n2) ( c 1 < 1 c1<1 c1<1)
代码
#include
#define int long long
using namespace std;
int t,n,a[10005];
signed main()
{
cin>>t;
while (t--)
{
int tot=0,ans=0;
bool visited[10005]={0};
cin>>n;
for (int i=1;i<=n;i++) cin>>a[i];
for (int i=1;i<=n-1;i++)
{
int sumv=a[i];
for (int j=i+1;j<=n;j++)
{
sumv+=a[j];
if (sumv>n) break;
else visited[sumv]=1;
}
}
for (int i=1;i<=n;i++)
{
if (visited[a[i]]==1) ans++;
}
cout<<ans<<endl;
}
return 0;
}
难度: 普及/提高-
思路
先凑 a + 1 a+1 a+1个 1 1 1,再弄 c + 1 c+1 c+1个 0 0 0;然后随便搞一搞弄出 b b b个相邻且不同的位置即可。
注意 a + 1 a+1 a+1个1与 c + 1 c+1 c+1个0之间有一个交界处,那么 b b b就应该减去1。然后从 a + c + 3 a+c+3 a+c+3开始构造,每个数均为上一个数加上1模2的值(相当于0后1,1后0)。
题目保证有解!
代码
#include
#define int long long
using namespace std;
int t,a,b,c;
int s[1005];
signed main()
{
cin>>t;
while (t--)
{
int pos=0;
cin>>a>>b>>c;//0 4 0
if (a!=0)
{
for (int i=pos+1;i<=pos+a+1;i++) s[i]=0;
pos+=(a+1);
}
if (c!=0)
{
for (int i=pos+1;i<=pos+c+1;i++) s[i]=1;
pos+=(c+1);
}
if (b!=0)
{
if (a==0||b==0)
{
for (int i=pos+1;i<=pos+b+1;i++) s[i]=(s[i-1]+1)%2;
pos+=(b+1);
}
else
{
for (int i=pos+1;i<=pos+b;i++) s[i]=(s[i-1]+1)%2;
pos+=b;
}
}
for (int i=1;i<=a+b+c+1;i++) cout<<s[i];
cout<<endl;
}
return 0;
}
难度: 普及/提高-
思路
如果 n n n为1或2或3,直接输出-1。
如果 n n n为奇数,则这么构造:
① n = 5 n=5 n=5时, P = 1 , 3 , 5 , 2 , 4 P={1,3,5,2,4} P=1,3,5,2,4
② n = 11 n=11 n=11时, P = 1 , 3 , 5 , 7 , 9 , 11 , 8 , 10 , 6 , 4 , 2 P={1,3,5,7,9,11,8,10,6,4,2} P=1,3,5,7,9,11,8,10,6,4,2
如果 n n n为偶数,则这么构造:
① n = 4 n=4 n=4时, P = 2 , 4 , 1 , 3 P={2,4,1,3} P=2,4,1,3
② n = 12 n=12 n=12时, P = 2 , 4 , 6 , 8 , 10 , 12 , 9 , 11 , 7 , 5 , 3 , 1 P={2,4,6,8,10,12,9,11,7,5,3,1} P=2,4,6,8,10,12,9,11,7,5,3,1
如果您并不会做这一题,建议您找一下上面我构造的数组的规律。
然后上惨不忍睹的代码~
#include
#define int long long
using namespace std;
int t,n;
int a[1005];
signed main()
{
cin>>t;
while (t--)
{
cin>>n;
if (n==1||n==2||n==3)
{
cout<<"-1"<<endl;
continue;
}
if (n%2==0)
{
for (int i=1;i<=(n/2);i++) a[i]=i*2;
a[(n/2)+1]=a[(n/2)]-3;
a[(n/2)+2]=a[(n/2)+1]+2;
for (int i=(n/2)+3;i<=n;i++)
{
a[i]=a[i-1]-2;
if (a[i]==a[(n/2)+1]||a[i]==a[(n/2)+2]) a[i]-=2;
}
}
else if (n%2==1)
{
for (int i=1;i<=(n/2)+1;i++) a[i]=i*2-1;
a[(n/2)+2]=a[(n/2)+1]-3;
a[(n/2)+3]=a[(n/2)+2]+2;
for (int i=(n/2)+4;i<=n;i++)
{
a[i]=a[i-1]-2;
if (a[i]==a[(n/2)+2]||a[i]==a[(n/2)+3]) a[i]-=2;
}
}
for (int i=1;i<=n;i++) cout<<a[i]<<' ';
cout<<endl;
}
return 0;
}
难度: 普及/提高-
①本蒟蒻的做题信息:
编号 | 做题时间 | UnAC次数 |
---|---|---|
A | 4min | 0 |
B | 9min | 0 |
C | 11min | 0 |
D | 26min | 0 |
E | 17min | 0 |
F | 35min | 4 |
G | 24min | 1 |
②排名: 1320
赶紧膜拜班里一位比我强太多,早就 A K AK AK的神犇。
③总结
做这种水题不能再这么慢了,总是失误——如果这是NOIP的话,我只能AC五题(只有一次提交机会啊)。
我还是太弱了~
撒花✿✿ヽ(°▽°)ノ✿撒花