这个题本来有希望在比赛里面出了的

当时也想着用递推 因为后面的数明显是由前面的推过来的

但是在计算的时候 因为判重的问题 。。。很无语。我打算用一个tot[i]来存i的总种树,tot[i]+=tot[j]//j为可以由j推到i的一系列数,但这样是不对的,会产生大量重复计算。。。

看了下标程才发现要用二维来计算出种类总数,f[i][j]+=sum(f[i-j][k]) 表示在推i数的时候,第一个素数为j的种类数,注意j一定为素数,而且k不能大于j。。。标程里面处理的比较简练,就学了下他的写法。

至于推导出式子,则可以用递归,比较简练的是用递推。

这是错误的代码:是我之前没把种类数计算好,并且推导式子用的是递归:

#include <iostream>
#include <cstdio>
#include <cstring>
#define N 210
#define ll unsigned long long
using namespace std;
ll n,k;
int dp[N][N],count[N],vis[N];
ll tot[N];
int tmp[N],prime[N],cnt;
void init()
{
for (int i=;i<N;i++)
tmp[i]=;
for (int i=;i<N;i++){
for (int j=;j*i<N;j++){
tmp[i*j]=;
}
}
cnt=;
for (int i=;i<N;i++){
if (tmp[i]) prime[cnt++]=i;
}
// for (int i=0;i<cnt;i++)
// cout<<prime[i]<<endl;
memset(tot,,sizeof tot);
memset(count,,sizeof count);
}
void solve()
{
dp[][count[]++]=;
dp[][count[]++]=;
tot[]=tot[]=;
tot[]=;
for (int i=;i<N;i++){
memset(vis,,sizeof vis);
if (tmp[i]){
dp[i][count[i]++]=i;
vis[i]=;
tot[i]++;
}
int up=lower_bound(prime,prime+cnt,i-)-prime;
while (prime[up]>i-) up--;
for (int j=up;j>=;j--){
int num=prime[j];
bool flag=;
for (int k=count[i-num]-;k>=;k--){
if (dp[i-num][k]>num) break;
flag=;
tot[i]+=tot[dp[i-num][k]];
}
if (flag)
dp[i][count[i]++]=num;
}
}
tot[]=tot[]=;
for(int i=;i<N;i++){
tot[i]=;
for (int j=;j<count[i];j++){
tot[i]+=tot[dp[i][j]];
}
}
int test=;
for (int i=;i<count[test];i++)
cout<<i<<" !!! "<<dp[test][i]<<endl;
for (int i=;i<N;i++)
cout<<i<<" "<<tot[i]<<endl;;
}
void print(ll num,ll ret)
{
if (num==) return;
ll sum=;
int i;
ll pre=;
cout<<num<<" "<<ret<<endl;
for (i=;i<count[num];i++){
sum+=tot[num-dp[num][i]];
if (sum>=ret) break;
pre+=tot[num-dp[num][i]];
}
//if (sum>ret) i--;
// printf("%d",dp[num][i]);
//if (num-dp[num][i]>0) printf("+");
ll nt=ret-pre;
print(num-dp[num][i],nt); }
int main()
{
init();
solve();
while (scanf("%llu%llu",&n,&k)!=EOF){
printf("%llu\n",tot[n]);
if (k>tot[n]) k=tot[n];
printf("%d=",n);
print(n,k);
printf("\n");
}
}
//200 15252874192862840692

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 210
using namespace std;
int f[N][N];
int prime[N],tot[N];
void init()
{
memset(prime,,sizeof prime);
for (int i=;i<N;i++)
for (int j=i+i;j<N;j+=i) prime[j]=; //预处理出素数
memset(f,,sizeof f);
f[][]=;
for (int i=;i<N;i++)//这里处理的非常简练,因为不存在的情况全部置为了0,所以省去了各种判断和限制,而且k是不会大于j的,使得计算结果不会出现重复。
for (int j=;j<=i;j++) if (!prime[j])
for (int k=;k<=j;k++){
f[i][j]+=f[i-j][k];
}
for (int i=;i<N;i++)
for (int j=;j<=i;j++)
tot[i]+=f[i][j];
}
int n,k;
int main()
{
init();
while (scanf("%d%d",&n,&k)!=EOF){
printf("%d\n",tot[n]);
printf("%d=",n);
if (k>tot[n]) k=tot[n];
int cur=n,flag=;;
while (n>){ //递推出式子,这里也处理的比较巧妙。值得学习
if (k>f[n][cur]){
k-=f[n][cur];
cur--;
}
else
{
if (flag++) printf("+");
printf("%d",cur);
n-=cur;
}
}
printf("\n");
}
return ;
}

CSU 1425 NUDT校赛 I题 Prime Summation的更多相关文章

  1. PKU2018校赛 H题 Safe Upper Bound

    http://poj.openjudge.cn/practice/C18H 题目 算平均数用到公式\[\bar{x}=\frac{x_1+x_2+x_3+\cdots+x_n}{n}\] 但如果用in ...

  2. 2018WFU校赛B题

    我们在ACM的题目中已经了解了什么是ACM了,ACM还是很残酷的了(ಥ _ ಥ),那么现在你就要解决一个ACM最简单的题了,简单到省赛和区域赛都不会出这种简单的题.ls很强,即使每年都在ACM这个大坑 ...

  3. 牛客网 2018年东北农业大学春季校赛 L题 wyh的天鹅

    链接:https://www.nowcoder.com/acm/contest/93/L来源:牛客网 时间限制:C/C++ 3秒,其他语言6秒空间限制:C/C++ 262144K,其他语言524288 ...

  4. QAU 17校赛 J题 剪丝带(完全背包变形)

    题意: 剪一段丝带,对于剪完后的每一段丝带长度必须是a,b,c 输入丝带的长度  n 和  a  b  c 输出一个整数,代表最多能剪成多少段 样例输入 5 5 3 2 7 5 5 2 样例输出 2 ...

  5. 上海高校金马五校赛 F题:1 + 2 = 3?

    链接:https://www.nowcoder.com/acm/contest/91/F来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K,其他语言26214 ...

  6. 福建工程学院第十四届ACM校赛M题题解 fwt进阶,手推三进制fwt

    第九集,结束亦是开始 题意: 大致意思就是给你n个3进制的数字,让你计算有多少对数字的哈夫曼距离等于i(0<=i<=2^m) 思路: 这个是一个防ak题,做法是要手推公式的fwt 大概就这 ...

  7. 福建工程学院第十四届ACM校赛G题题解

    外传:编剧说了不玩游戏不行 题意: 有n个石堆,我每次只能从某一堆中取偶数个石子,你取奇数个,我先手,先不能操作的人输.问最后谁能赢. 思路: 这个题仔细想想,就发现,取奇数的人有巨大的优势,因为假设 ...

  8. 福建工程学院第十四届ACM校赛B题题解

    第二集,未来的我发量这么捉急的吗 题意: 有n个数,请问有多少对数字(i,j)(1<=i<j<=n),满足(a[i]^a[j])+((a[i]&a[j])<<1) ...

  9. 记校赛水题----AK爷兼职计

    Description AK爷最近收到一份兼职,是去幼儿园看小朋友,AK爷认为看孩子这件事情很简单,但是事实并非如此.幼儿园里的孩子们喜欢数学,不仅九九乘法口诀倒背如流而且精通各种算法.某天,AK爷上 ...

随机推荐

  1. C#获取屏幕分辨率率

    C#获取屏幕的分辨率   在C#中获取当前屏幕的分辨率的方法 1:rectangle类. 命名空间为:system.Drawing. system.Drawing.Rectangle rec=Scre ...

  2. CAN分帧接收实现

    该版本程序实现了上电后先发送MACID检测功能,如果网络上有应答.则一直进行死循环,直到用户更改了本机的ID地址 才可以跳出循环体. 本单片机设置为双滤波 ,使目标地址为0X1F 实现了建立连接命令 ...

  3. java 立方变自身

    立方变自身 观察下面的现象,某个数字的立方,按位累加仍然等于自身. 1^3 = 1 8^3 = 512 5+1+2=8 17^3 = 4913 4+9+1+3=17 - 请你计算包括1,8,17在内, ...

  4. 网卡工作原理和wireshark混杂模式

    通过设置网卡为混杂模式就能捕获局域网内所有发包内容,包括非广播包和非发给自己主机的数据包 这是为什么呢? 即主机A发送一个数据包给主机B,我作为主机C怎么也能截获这个数据包呢,原理是什么? 我的网卡为 ...

  5. UVA - 1346 Songs (贪心+排序)

    题意:已知每首歌的标号,长度和播放频率,求一种播放顺序,使得最小,并且输出该播放顺序下第t首歌的标号. 分析: 1.长度越短,播放频率越大的歌排在前面,上式越小. 2.s(i)表示的是当前播放顺序下这 ...

  6. POJ 1565:Skew Binary

    Skew Binary Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 10676   Accepted: 6807 Desc ...

  7. redis : Can't save in background: fork: Cannot allocate memory

    redis : Can't save in background: fork: Cannot allocate memory JAVA程序报错信息: MISCONF Redis is configur ...

  8. 指令——touch

    一个完整的指令的标准格式: Linux通用的格式——#指令主体(空格) [选项](空格) [操作对象] 一个指令可以包含多个选项,操作对象也可以是多个. 指令:touch    作用:创建文件 语法: ...

  9. 004、mysql使用SHOW语句找出服务器上当前存在什么数据库

    SHOW DATABASES; 不忘初心,如果您认为这篇文章有价值,认同作者的付出,可以微信二维码打赏任意金额给作者(微信号:382477247)哦,谢谢.

  10. Newtonsoft.Json版本冲突

    如果项目中不同第三方类库分别使用了不同版本的Newtonsoft.Json,可以在配置文件中添加以下节点,将0.0.0.0-9.0.0.0此区间的Newtonsoft.Json使用全部强制指向到项目中 ...