CSU 1810 Reverse

湖南省第十二届大学生计算机程序设计竞赛$H$题

规律,递推。

这种问题一看就有规律。可以按位统计对答案的贡献。即第$1$位对答案作出了多少贡献,第$2$位对答案作出了多少贡献.....累加和就是答案。

先写一个暴力的程序来找找规律:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0),eps=1e-6;
void File()
{
    freopen("D:\\in.txt","r",stdin);
    freopen("D:\\out.txt","w",stdout);
}
template <class T>
inline void read(T &x)
{
    char c = getchar();
    x = 0;
    while(!isdigit(c)) c = getchar();
    while(isdigit(c))
    {
        x = x * 10 + c - ‘0‘;
        c = getchar();
    }
}

const int maxn=1010;
struct X
{
    int p;
}s[maxn];
int n;
int f[maxn][maxn];

int main()
{
    while(~scanf("%d",&n))
    {
        memset(f,0,sizeof f);
        for(int i=1;i<=n;i++) s[i].p=i;

        for(int i=1;i<=n;i++)
        {
            for(int j=i;j<=n;j++)
            {
                for(int k=i;k<=(i+j)/2;k++) swap(s[k],s[j-(k-i)]);

                for(int k=1;k<=n;k++) f[s[k].p][k]++;

                for(int k=i;k<=(i+j)/2;k++) swap(s[k],s[j-(k-i)]);
            }
        }

        for(int i=1;i<=n;i++)
        {
            int sum=0;
            for(int j=1;j<=n;j++)
            {
               // sum=sum+(int)pow(10.0,j-1)*f[i][j];
                printf("%3d ",f[i][j]);
            }
            printf("\n");
          //  printf("%d ",sum);
        }
        printf("\n");

    }
    return 0;
}

上面的代码中,$f[i][j]$表示$i$这一位,所有交换中,在$j$位出现了几次;答案就是$\sum\limits_{i = 1}^n {\left( {s[i]×\left( {\sum\limits_{j = 1}^n {f[i][j]×{{10}^{j - 1}}} } \right)} \right)} $。

输出来看一下$n=10$和$n=11$时候的情况,看看$f[i][j]$有没有什么规律:

通过观察可以发现:

$[1].$每一行的和都是一样的,$n=x$时,每一行的和$cnt[x]$都是一样的,并且$cnt[x]=x+cnt[x-1]$。

$[2].$第$i$行的贡献${\sum\limits_{j = 1}^n {f[i][j]×{{10}^{j - 1}}} }$可以由第$i-1$行的贡献${\sum\limits_{j = 1}^n {f[i-1][j]×{{10}^{j - 1}}} }$递推而来。

也就是说,我们可以$O(n)$效率得到每一位的贡献,然后乘上输入的那个权值就是答案了。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi = acos(-1.0), eps = 1e-8;
void File()
{
    freopen("D:\\in.txt", "r", stdin);
    freopen("D:\\out.txt", "w", stdout);
}
template <class T>
inline void read(T &x)
{
    char c = getchar(); x = 0; while (!isdigit(c)) c = getchar();
    while (isdigit(c)) { x = x * 10 + c - ‘0‘; c = getchar(); }
}

const LL mod = 1e9 + 7;
const int maxn = 100010;
LL a[maxn], cnt[maxn], POW[maxn], sPOW[maxn], num[maxn];
char s[maxn];
int n;

int main()
{
    cnt[1] = 1;
    for (int i = 2; i <= 100000; i++) cnt[i] = (cnt[i - 1] + i) % mod;
    POW[0] = 1; sPOW[0] = 1;
    for (int i = 1; i <= 100000; i++)
    {
        POW[i] = (LL)10 * POW[i - 1] % mod;
        sPOW[i] = (sPOW[i - 1] + POW[i]) % mod;
    }

    while (~scanf("%d%s", &n, s))
    {
        memset(num, 0, sizeof num);
        memset(a, 0, sizeof a);

        num[0] = (cnt[n] - (n - 1) + mod) % mod;
        a[0] = (num[0]*POW[0] % mod + (sPOW[n - 1] - sPOW[0] + mod) % mod) % mod;

        int L = 1, R = n - 1;
        for (int i = 1; i < n / 2; i++)
        {
            L++, R--; num[i] = (num[i - 1] - (R - L + 1) + mod) % mod;
            a[i] = (a[i - 1] + sPOW[R] - sPOW[L - 1] + mod) % mod;
            a[i] = (a[i] + ((num[i] - i + mod) % mod)*POW[i] % mod) % mod;
            a[i] = (a[i] - (((num[i - 1] - i + mod) % mod)*POW[i - 1] % mod) + mod) % mod;
        }

        num[n - 1] = num[0];
        a[n - 1] = (num[n - 1] * POW[n - 1] % mod + sPOW[n - 2]) % mod;

        L = 0, R = n - 2; LL d = 1;
        for (int i = n - 2; i >= (n ) / 2; i--)
        {
            L++, R--; num[i]= (num[i + 1] - (R - L + 1) + mod) % mod;
            a[i]= (a[i + 1] + sPOW[R] - sPOW[L - 1] + mod) % mod;
            a[i] = (a[i] + ((num[i] - d + mod) % mod)*POW[i] % mod) % mod;
            a[i] = (a[i] - (((num[i + 1] - d + mod) % mod)*POW[i + 1] % mod) + mod) % mod;
            d++;
        }

        LL ans = 0;
        for (int i = 0; s[i]; i++) ans = (ans + (LL)(s[i] - ‘0‘)*a[n-i-1] % mod) % mod;
        cout << ans << endl;
    }
    return 0;
}
时间: 2024-10-12 20:36:02

CSU 1810 Reverse的相关文章

【数学】CSU 1810 Reverse (2016湖南省第十二届大学生计算机程序设计竞赛)

题目链接: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1810 题目大意: 一个长度为N的十进制数,R(i,j)表示将第i位到第j位翻转过来后的数字,求mod 109+7 题目思路: [数学] 这题换一种思路,看每个数字能够对答案的贡献情况.(可以手推01,10,001,010,100.....,也可以像我一样写个暴力打个10以内的表看看规律) 现在先考虑位置为i的数字为1的情况(最后乘上这个数字就行).可以发现贡献是对称的(第i位的1和第

湖南多校对抗赛(2015.4.6)CSU 1561~1569 题解

A:点击打开链接 CSU 1561 (More)Multiplication 题意:把两个数的乘积每个位置的结果填充上去. 注意这个矩阵最大是1e8,所以不能开数组. 模拟题 #include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cmath> #include <cstring> #include <queue

CSU 1561-(More) Multiplication

题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1561 题面: 1561: (More) Multiplication Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 180  Solved: 95 [Submit][Status][Web Board] Description Educators are always coming up with new ways to teach m

Django url 标签和reverse()函数的使用(转)

原文:http://www.yihaomen.com/article/python/355.htm 使用url标签和reverse()函数,可以避免在模板和view中对url进行硬编码,这样即使url改变了,对模板和view也没有影响 起初用django 开发应用的时候,完全是在urls.py 中硬编码配置地址,在views.py中HttpResponseRedirect()也是硬编码转向地址,当然在template 中也是一样了,这样带来一个问题,如果在urls.py 中修改了某个页面的地址,

186. Reverse Words in a String II

https://leetcode.com/problems/reverse-words-in-a-string-ii/#/description Given an input string, reverse the string word by word. A word is defined as a sequence of non-space characters. The input string does not contain leading or trailing spaces and

CSU 1804: 有向无环图(拓扑排序)

http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1804 题意:…… 思路:对于某条路径,在遍历到某个点的时候,之前遍历过的点都可以到达它,因此在这个时候对答案的贡献就是∑(a1 + a2 + a3 + ... + ai) * bv,其中a是之前遍历到的点,v是当前遍历的点. 这样想之后就很简单了.类似于前缀和,每次遍历到一个v点,就把a[u]加给a[v],然后像平时的拓扑排序做就行了. 1 #include <bits/stdc++.h>

CSU 1111: 三家人【有趣的思维题】

1111: 三家人 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 2241  Solved: 874 [Submit][Status][Web Board] Description 有三户人家共拥有一座花园,每户人家的太太均需帮忙整理花园.A 太太工作了5 天,B 太太则工作了4 天,才将花园整理完毕.C 太太因为正身怀六甲无法加入她们的行列,便出了90元.请问这笔钱如何分给A.B 二位太太较为恰当?A 应得多少元?90/(5+4)*5=$50

CSU 1112: 机器人的指令【模拟题】

1112: 机器人的指令 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 1858  Solved: 682 [Submit][Status][Web Board] Description 数轴原点有一个机器人.该机器人将执行一系列指令,你的任务是预测所有指令执行完毕之后它的位置. ·LEFT:往左移动一个单位 ·RIGHT: 往右移动一个单位 ·SAME AS i: 和第i 条执行相同的动作.输入保证i 是一个正整数,且不超过之前执行指令数 In

codeforces 414C C. Mashmokh and Reverse Operation(归并排序求逆序对)

题目链接: C. Mashmokh and Reverse Operation time limit per test 4 seconds memory limit per test 512 megabytes input standard input output standard output Mashmokh's boss, Bimokh, didn't like Mashmokh. So he fired him. Mashmokh decided to go to university